linq group by contiguous blocks

Solution 1:

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

And then it's as simple as:

var groups = myData.GroupAdjacent(data => data.OnOffStatus);

Solution 2:

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

Solution 3:

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));

Solution 4:

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..