2010-10-19 9 views
17

क्या यह जानने का एक लिंक तरीका है कि अनुक्रम में अगला तत्व पुनरावृत्ति के दौरान क्या होता है? एक ठोस उदाहरण के रूप में, मैं ints की एक सूची है कहते हैं, और मैं प्रत्येक तत्व और उसके उत्तराधिकारी के बीच अंतर की गणना करना चाहते हैं, तो उदाहरण के लिए मैंसूची में तत्व और अगले तत्व के बीच टुकड़े के अंतर को पाने के लिए लिंक

var myList = new List<int>() { 1,3,8,2,10 }; 
var differences = myList.Select(ml => ml.Next() - ml) // pseudo-code, obviously 

जहां परिणाम मैं चाहता हूँ लिखने में सक्षम होना चाहते हैं एक सूची {2,5, -6,8} है।

स्पष्ट रूप से यह लूप के लिए छोटा है, लेकिन क्या कोई इस काम को करने के लिए लिंक में एक साफ लाइनर के बारे में सोच सकता है?

+0

इस सवाल आप http://stackoverflow.com/questions/2680228/linq-next-item-in-list मदद कर सकता है –

उत्तर

32

आप .NET 4 तो उपयोग कर रहे हैं आप कर सकते थे Zip और Skip:

var differences = myList.Zip(myList.Skip(1), (x, y) => y - x); 

आप ढांचे के एक पुराने संस्करण का उपयोग कर रहे हैं, और/या आप एक थोड़ा अधिक कुशल तरीका चाहता था ऐसा करने का है, तो आप एक सरल विस्तार विधि बना सकते हैं:

var differences = myList.Pairwise((x, y) => y - x); 

// ... 

public static class EnumerableExtensions 
{ 
    public static IEnumerable<T> Pairwise<T>(
     this IEnumerable<T> source, Func<T, T, T> selector) 
    { 
     if (source == null) throw new ArgumentNullException("source"); 
     if (selector == null) throw new ArgumentNullException("selector"); 

     using (var e = source.GetEnumerator()) 
     { 
      if (!e.MoveNext()) throw new InvalidOperationException("Sequence cannot be empty."); 

      T prev = e.Current; 

      if (!e.MoveNext()) throw new InvalidOperationException("Sequence must contain at least two elements."); 

      do 
      { 
       yield return selector(prev, e.Current); 
       prev = e.Current; 
      } while (e.MoveNext()); 
     } 
    } 
} 
+0

इसे प्यार; यह वही है जो मैंने जवाब दिया होगा, मुझे पता था कि एक ज़िप() फ़ंक्शन मौजूद था। – KeithS

+0

@ किथ या आप इसे .NET 3.5 के लिए MoreLinq से उपयोग कर सकते हैं। –

+0

इस समाधान का एकमात्र मामूली कमी यह है कि मेरी सूची दो बार गणना की जाएगी। .NET (Rx) के लिए प्रतिक्रियाशील एक्सटेंशन से ज्ञापन विधि के साथ हालांकि आसानी से तय किया जा सकता है। –

5
var differences = myList 
    .Take(myList.Count - 1) 
    .Select((v, i) => myList[i + 1] - v); 

सूची मानते हुए कम से कम 2 आइटम हैं।

संबंधित मुद्दे