How to separate all consecutive objects using Linq (C #)

I have List<MyObject>... MyObject has the LineId (integer) property ...

So, I need to split all consecutive LineId in List ...

Example:

List<MyObject> :

LineId =1
LineId =1
LineId =1
LineId =2
LineId =1
LineId =2

The result should consist of 4 divided lists:

LineId =1
LineId =1
LineId =1
-------------
LineId =2
-------------
LineId =1
-------------
LineId =2

So, I have to separate all consecutive LineId ...

Is there an easy way to do this with Linq?

thank

+3
source share
6 answers

It looks ugly, but the idea is clear, and I think it works:

var agg = list.Aggregate(
    new List<List<Line>>(),
    (groupedLines, line) => {
        if (!groupedLines.Any()) {
            groupedLines.Add(new List<Line>() { line });
        }
        else {
            List<Line> last = groupedLines.Last();
            if (last.First().LineId == line.LineId) {
                last.Add(line);
            }
            else {
                List<Line> newGroup = new List<Line>();
                newGroup.Add(line);
                groupedLines.Add(newGroup);
            }
        }
        return groupedLines;
    }
);

Here I assume that you have:

class Line { public int LineId { get; set; } }

and

List<Line> list = new List<Line>() {
    new Line { LineId = 1 },
    new Line { LineId = 1 },
    new Line { LineId = 1 },
    new Line { LineId = 2 },
    new Line { LineId = 1 },
    new Line { LineId = 2 }
};

Now if i do

foreach(var lineGroup in agg) {
    Console.WriteLine(
        "Found {0} consecutive lines with LineId = {1}",
        lineGroup.Count,
        lineGroup.First().LineId
    );
    foreach(var line in lineGroup) {
        Console.WriteLine("LineId = {0}", line.LineId);
    }
}

I see:

Found 3 consecutive lines with LineId = 1
LineId = 1
LineId = 1
LineId = 1
Found 1 consecutive lines with LineId = 2
LineId = 2
Found 1 consecutive lines with LineId = 1
LineId = 1
Found 1 consecutive lines with LineId = 2
LineId = 2

printed on the console.

+2
source

, , linq . , , , , LINQ.

            List<MyObject> currentList = new List<MyObject>();
            List<List<MyObject>> finalList = new List<List<MyObject>>();
            for (int i = 0; i < myObjects.Count; i++)
            {
                //If the list is empty, or has the same LineId, add to it.
                if (currentList.Count == 0 || currentList[0].LineId == myObjects[i].LineId)
                {
                    currentList.Add(myObjects[i]);
                }
                //Otherwise, create a new list.
                else
                {
                    finalList.Add(currentList);
                    currentList = new List<MyObject>();
                    currentList.Add(myObjects[i]);
                }
            }
            finalList.Add(currentList);

, linq, , , , .

+3

, LINQ, LINQ:

public static IEnumerable<IEnumerable<TSource>> GroupConsecutive<TSource,TKey>(
        this IEnumerable<TSource> source, Func<TSource,TKey> keySelector) {
    if (source == null) throw new ArgumentNullException("source");
    if (keySelector == null) throw new ArgumentNullException("keySelector");

    var comparer = EqualityComparer<TKey>.Default;
    var grouped = new List<TSource>();
    using (var iter = source.GetEnumerator()) {
        if (!iter.MoveNext()) yield break;
        grouped.Add(iter.Current);
        var last = iter.Current;
        while (iter.MoveNext()) {
            if (!comparer.Equals(keySelector(iter.Current), keySelector(last))) {
                yield return grouped.AsReadOnly();
                grouped = new List<TSource>();
            }
            grouped.Add(iter.Current);
            last = iter.Current;
        }
        yield return grouped.AsReadOnly();
    }
}
+3

, , , (: ) :

var lst = new [] {
    new { LineID = 1 },
    new { LineID = 1 },
    new { LineID = 1 },
    new { LineID = 2 },
    new { LineID = 1 },
    new { LineID = 2 },
};

var q = lst
    .Select((x,i) => new {Item = x, Index = i})
    .GroupBy(x => x.Item)
    .SelectMany(x => x.Select((y,i) => new { Item = y.Item, Index = y.Index, Sort = i - y.Index }))
    .OrderBy(x => x.Index)
    .GroupBy(x => x.Sort)
    .Select(x => x.Select(y => y.Item));

IEnumerable<IEnumerable<int>>:

1,1,1
2
1
2

, , "OrderBy" "Index = y.Index" , :

1,1,1
1
2
2
+2

, .

:

LineId    Index     Boundary Index
  1         0           2
  1         1           2
  1         2           2
  2         3           3
  1         4           4
  2         5           5

Linq:

var lines = new List<MyObject>
                {
                    new MyObject { LineId = 1 },
                    new MyObject { LineId = 1 },
                    new MyObject { LineId = 1 },
                    new MyObject { LineId = 2 },
                    new MyObject { LineId = 1 },
                    new MyObject { LineId = 2 },
                };

IEnumerable<List<int>> consecutiveLineIds = lines
    .Select((line, i) => new
    {
        Line = line,
        Boundary = i + lines.Skip(i)
                            .TakeWhile(l => l.LineId == line.LineId).Count() - 1
    })
    .GroupBy(item => item.Boundary, item => item.Line.LineId)
    .Select(g => g.ToList());
+1
void Main()
{
    var list = new []{
        new { LineId = 1 },
        new { LineId = 1 },
        new { LineId = 1 },
        new { LineId = 2 },
        new { LineId = 2 },
        new { LineId = 1 },
        new { LineId = 1 },
        new { LineId = 3 },
        new { LineId = 3 },
        new { LineId = 1 }
    };

    var groups =    
        from i in list
        group i by i.LineId into g
        select new { LineId = g.Key, MyObject = g };
}
0
source

Source: https://habr.com/ru/post/1773122/


All Articles