alpinescrambler
alpinescrambler

Reputation: 1954

Split array or list into segments using LINQ

This question is slightly different from here

I have an array of numbers where I want to produce a list of segments. The end of the segment is included as the beginning element of the next segment. I want each segment to have 3 (in this example) points each. Here's an illustration:

var origArray = new[] {1,2,3,4,5,6};

I want the result to be:

{ {1,2,3}, {3,4,5}, {5,6} }

A traditional for-loop could accomplish this, but just wondering if somebody did this in a LINQy way.

Upvotes: 0

Views: 1013

Answers (2)

Enigmativity
Enigmativity

Reputation: 117064

Try adding the Microsoft's Reactive Framework Team's Interactive Extensions - just NuGet "Ix-Main".

Then you can do this:

var origArray = new[] {1,2,3,4,5,6};
var result = origArray.Buffer(3, 2);

The two parameters are "how many to group", 3, and "how many to skip", 2.

The result is as you expect: { {1,2,3}, {3,4,5}, {5,6} }.

This is their implementation from https://github.com/dotnet/reactive/blob/main/Ix.NET/Source/System.Interactive/System/Linq/Operators/Buffer.cs:

    private static IEnumerable<IList<TSource>> Buffer_<TSource>(this IEnumerable<TSource> source, int count, int skip)
    {
        var buffers = new Queue<IList<TSource>>();

        var i = 0;
        foreach (var item in source)
        {
            if (i%skip == 0)
                buffers.Enqueue(new List<TSource>(count));

            foreach (var buffer in buffers)
                buffer.Add(item);

            if (buffers.Count > 0 && buffers.Peek()
                                            .Count == count)
                yield return buffers.Dequeue();

            i++;
        }

        while (buffers.Count > 0)
            yield return buffers.Dequeue();
    }

Upvotes: 3

Vishal Madhvani
Vishal Madhvani

Reputation: 442

Two possible ways to do this using Linq.

var segmentedArray1 = origArray
    .Select((item, index) => new { item, index })
    .GroupBy(x => x.index/3)
    .Select(@group => @group.Select(x=>x.item));

var segmentedArray2 = Enumerable.Range(0, origArray.Count())
    .GroupBy(x => x/3)
    .Select(@group => @group.Select(index => origArray[index]));

Here's a dotnetfiddle

Upvotes: 0

Related Questions