linq group by contiguous blocks

前端 未结 5 1419
长情又很酷
长情又很酷 2020-12-02 00:01

Let\'s say I have following data:

Time Status
10:00 On
11:00 Off
12:00 Off
13:00 Off
14:00 Off<

相关标签:
5条回答
  • 2020-12-02 00:08

    You could also do this with one Linq query using a variable to keep track of the changes, like this.

    int key = 0;
    var query = data.Select(
        (n,i) => i == 0 ? 
            new { Value = n, Key = key } : 
            new 
            { 
                Value = n, 
                Key = n.OnOffFlag == data[i - 1].OnOffFlag ? key : ++key 
            })
        .GroupBy(a => a.Key, a => a.Value);
    

    Basically it assigns a key for each item that increments when the current item does not equal the previous item. Of course this assumes that your data is in a List or Array, otherwise you'd have to try a different method

    0 讨论(0)
  • 2020-12-02 00:09

    It can be done as.

    1. Iterate over collection.
    2. Use TakeWhile<Predicate> condition is text of first element of collection On or Off.
    3. Iterate over the subset of from point one and repeat above step and concatenate string.

    Hope it helps..

    0 讨论(0)
  • 2020-12-02 00:19

    Create a GroupAdjacent extension, such as the one listed here.

    And then it's as simple as:

    var groups = myData.GroupAdjacent(data => data.OnOffStatus);
    
    0 讨论(0)
  • 2020-12-02 00:26

    Here is a hardcore LINQ solution by using Enumerable.Zip to compare contiguous elements and generate a contiguous key:

    var adj = 0;
    var t = data.Zip(data.Skip(1).Concat(new TimeStatus[] { null }),
            (x, y) => new { x, key = (x == null || y == null || x.Status == y.Status) ? adj : adj++ }
        ).GroupBy(i => i.key, (k, g) => g.Select(e => e.x));
    
    0 讨论(0)
  • 2020-12-02 00:29

    You could parse the list and assign a contiguous key e.g define a class:

    public class TimeStatus
    {
        public int ContiguousKey { get; set; }
        public string Time { get; set; }
        public string Status { get; set; }
    }
    

    You would assign values to the contiguous key by looping through, maintaining a count and detecting when the status changes from On to Off and so forth which would give you a list like this:

    List<TimeStatus> timeStatuses = new List<TimeStatus> 
                {
                    new TimeStatus { ContiguousKey = 1, Status = "On", Time = "10:00"},
                    new TimeStatus { ContiguousKey = 1, Status = "On", Time = "11:00"},
                    new TimeStatus { ContiguousKey = 2, Status = "Off", Time = "12:00"},
                    new TimeStatus { ContiguousKey = 2, Status = "Off", Time = "13:00"},
                    new TimeStatus { ContiguousKey = 2, Status = "Off", Time = "14:00"},
                    new TimeStatus { ContiguousKey = 3, Status = "On", Time = "15:00"},
                    new TimeStatus { ContiguousKey = 3, Status = "On", Time = "16:00"}
                };
    

    Then using the following query you can extract the Status and grouped Times:

        var query = timeStatuses.GroupBy(t => t.ContiguousKey)
        .Select(g => new { Status = g.First().Status, Times = g });
    
    0 讨论(0)
提交回复
热议问题