Reputation: 1954
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
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
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