Ottenere il set di coppie usando LINQ

Quando ho una lista

IList list = new List(); list.Add(100); list.Add(200); list.Add(300); list.Add(400); list.Add(500); 

Qual è il modo di estrarre una coppia

 Example : List elements {100,200,300,400,500} Expected Pair : { {100,200} ,{200,300} ,{300,400} ,{400,500} } 

Questo ti darà una serie di oggetti “pair” anonimi con proprietà A e B corrispondenti agli elementi pair.

 var pairs = list.Where( (e,i) => i < list.Count - 1 ) .Select( (e,i) => new { A = e, B = list[i+1] } ); 

Il modo più elegante con LINQ: list.Zip(list.Skip(1), Tuple.Create)

Un esempio di vita reale: questo metodo di estensione prende una raccolta di punti ( Vector2 ) e produce una raccolta di linee ( PathSegment ) necessarie per “unire i punti”.

 static IEnumerable JoinTheDots(this IEnumerable dots) { var segments = dots.Zip(dots.Skip(1), (a,b) => new PathSegment(a, b)); return segments; } 

Puoi usare un ciclo for:

 var pairs = new List(); for(int i = 0; i < list.Length - 1; i++) pairs.Add(new [] {list[i], list[i + 1]); 

Puoi anche usare LINQ, ma è più brutto:

 var pairs = list.Take(list.Count - 1).Select((n, i) => new [] { n, list[i + 1] }); 

EDIT : Puoi anche farlo su un IEnumerable non IEnumerable , ma è molto più brutto:

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

Più generale sarebbe:

  public static IEnumerable Pairwise(this IEnumerable values, int count, Func 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; } } } 

La seguente soluzione utilizza il metodo zip. Zip originalList e originalList.Skip (1) in modo da ottenere il risultato desiderato.

  var adjacents = originalList.Zip(originalList.Skip(1), (a,b) => new {N1 = a, N2 = b}); 

Fuori dalla mia testa e completamente non testati:

 public static T Pairwise(this IEnumerable list) { T last; bool firstTime = true; foreach(var item in list) { if(!firstTime) return(Tuple.New(last, item)); else firstTime = false; last = item; } } 

Utilizzando .Windowed() da MoreLINQ :

 var source = new[] {100,200,300,400,500}; var result = source.Windowed(2).Select(x => Tuple.Create(x.First(),x.Last()));