Getting pair-set using LINQ
12,478
Solution 1
This will give you an array of anonymous "pair" objects with A and B properties corresponding to the pair elements.
var pairs = list.Where( (e,i) => i < list.Count - 1 )
.Select( (e,i) => new { A = e, B = list[i+1] } );
Solution 2
The most elegant way with LINQ: list.Zip(list.Skip(1), Tuple.Create)
A real-life example: This extension method takes a collection of points (Vector2
) and produces a collection of lines (PathSegment
) needed to 'join the dots'.
static IEnumerable<PathSegment> JoinTheDots(this IEnumerable<Vector2> dots)
{
var segments = dots.Zip(dots.Skip(1), (a,b) => new PathSegment(a, b));
return segments;
}
Solution 3
You can use a for loop:
var pairs = new List<int[]>();
for(int i = 0; i < list.Length - 1; i++)
pairs.Add(new [] {list[i], list[i + 1]);
You can also use LINQ, but it's uglier:
var pairs = list.Take(list.Count - 1).Select((n, i) => new [] { n, list[i + 1] });
EDIT: You can even do it on a raw IEnumerable
, but it's much uglier:
var count = list.Count();
var pairs = list
.SelectMany((n, i) => new [] { new { Index = i - 1, Value = n }, new { Index = i, Value = n } })
.Where(ivp => ivp.Index >= 0 && ivp.Index < count - 1) //We only want one copy of the first and last value
.GroupBy(ivp => ivp.Index, (i, ivps) => ivps.Select(ivp => ivp.Value));
Solution 4
More general would be:
public static IEnumerable<TResult> Pairwise<TSource, TResult>(this IEnumerable<TSource> values, int count, Func<TSource[], TResult> pairCreator)
{
if (count < 1) throw new ArgumentOutOfRangeException("count");
if (values == null) throw new ArgumentNullException("values");
if (pairCreator == null) throw new ArgumentNullException("pairCreator");
int c = 0;
var data = new TSource[count];
foreach (var item in values)
{
if (c < count)
data[c++] = item;
if (c == count)
{
yield return pairCreator(data);
c = 0;
}
}
}
Solution 5
Following solution uses zip method. Zip originalList and originalList.Skip(1) so that one gets desired result.
var adjacents =
originalList.Zip(originalList.Skip(1),
(a,b) => new {N1 = a, N2 = b});
Related videos on Youtube
Author by
user160677
Updated on April 17, 2022Comments
-
user160677 about 2 years
When i have a list
IList<int> list = new List<int>(); list.Add(100); list.Add(200); list.Add(300); list.Add(400); list.Add(500);
What is the way to extract a pairs
Example : List elements {100,200,300,400,500} Expected Pair : { {100,200} ,{200,300} ,{300,400} ,{400,500} }
-
leppie over 14 yearsPlease specify your problem better. What you have now can mean one of any number of things...
-
SLaks over 14 yearsDo you want to operate on a raw
IEnumerable
or only anIList<T>
? If so, see my edit.
-
-
GameKyuubi over 7 yearsCan someone explain what this does? It's quite dense.
-
tvanfosson over 7 years@GameKyuubi the
(e,i)
notation represents the signature that takes both the element and the index of the element. TheWhere
clause allows all but the last element in the sequence. TheSelect
clause creates a new anonymous object with theA
element assigned the original element in the sequence and theB
element assigned the following element in the sequence. That is, ife
represents thei
th element at each iteration, thenB
gets thei+1
th element.