2010-02-28 8 views
8

कुल डेल्टा नहीं बल्कि प्रत्येक तत्व का डेल्टा। यहाँ समझाने के लिए मैं क्या मतलब है कुछ कोड है:क्या मुझे LINQ में दो IENumerables का डेल्टा मिल सकता है?

var deltaTotals = _deltaEnumerable.Select(a => a.Amount).ToList(); 
var oldTotals = _totalsEnumerable.Select(d => d.Amount).ToList(); 

// trigger change in _totalsEnumerable 

// ** can LINQ do the lines below 
var newTotals = totalsEnumerable.Select(d => d.Amount); 
for (var i = 0; i < 7; i++) { 
    var newAmount = oldTotals[i] - deltaTotals[i]; 
    Assert.That(newTotals.ElementAt(i), Is.EqualTo(newAmount)); 
} 

यह कोड के अंतिम चार लाइनें लग रहे है कि किसी तरह LINQ में करने के लिए एक और अधिक सुरुचिपूर्ण तरीका हो सकता है की तरह है।

चीयर्स,
Berryl

उत्तर

7

आप क्या चाहते हैं Enumerable.Zip विस्तार विधि।

एक उदाहरण उपयोग होगा:

var delta = oldTotals.Zip(newTotals, (o, n) => n.Amount - o.Amount); 

ध्यान दें कि यह .NET 4.0 के लिए नया है। .NET 3.5 में आपको अपना स्वयं का एक्सटेंशन लिखना होगा। कुछ इस तरह:

public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult>(
    this IEnumerable<TFirst> first, 
    IEnumerable<TSecond> second, 
    Func<TFirst, TSecond, TResult> resultSelector) 
{ 
    using (var firstEnumerator = first.GetEnumerator()) 
    using (var secondEnumerator = second.GetEnumerator()) 
    { 
     while ((firstEnumerator.MoveNext() && secondEnumerator.MoveNext())) 
     { 
      yield return resultSelector(firstEnumerator.Current, 
       secondEnumerator.Current); 
     } 
    } 
} 
+0

कूल। ज़िप मुझे सबसे अधिक इरादे से प्रकट करने वाले नाम की तरह प्रतीत नहीं होता है लेकिन कम से कम यह छोटा है। जब मैंने पहली बार आपका जवाब देखा तो मैंने सोचा कि यह एक डाउनलोड था! चीयर्स – Berryl

+0

सच है, यह दुनिया में सबसे अधिक खोजने योग्य नाम नहीं है। मुझे लगता है कि एरिक लिपर्ट ने इस शब्द को बनाया: http://blogs.msdn.com/ericlippert/archive/2009/05/07/zip-me-up.aspx। किसी भी तरह से, यह एक उपयोगी विस्तार है। :) – Aaronaught

+2

नाम कार्यात्मक भाषाओं से आता है। इसे ऐसा कहा जाता है क्योंकि यह एक जिपर की तरह काम करता है। डिफ़ॉल्ट रूप से इसे फॉर्म टुपल्स की तरह कुछ करना चाहिए जहां पहला तत्व सूची 1 से दूसरे 2 से आता है। – flq

5

Aaronaught के रूप में अपने जवाब में कहा, आप Zip विधि का उपयोग करना चाहिए, हालांकि, यह .NET 3.5 में उपलब्ध नहीं है, केवल 4.0 में। यहां एक कस्टम कार्यान्वयन है:

public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult>(this IEnumerable<TFirst> first, IEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> selector) 
    { 
     if (first == null) 
      throw new ArgumentNullException("first"); 
     if (second == null) 
      throw new ArgumentNullException("second"); 
     if (selector == null) 
      throw new ArgumentNullException("selector"); 

     return first.ZipIterator(second, selector); 
    } 

    private static IEnumerable<TResult> ZipIterator<TFirst, TSecond, TResult>(this IEnumerable<TFirst> first, IEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> selector) 
    { 
     using (var enum1 = first.GetEnumerator()) 
     using (var enum2 = second.GetEnumerator()) 
     { 
      while (enum1.MoveNext() && enum2.MoveNext()) 
      { 
       yield return selector(enum1.Current, enum2.Current); 
      } 
     } 
    } 
+0

स्वीट। 4.0 में ज़िप जैसे अधिक एक्सटेंशन हैं? – Berryl

+0

संख्यात्मक कक्षा में ज़िप एकमात्र नई विधि है, लेकिन कहीं और हो सकता है ... –

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