2010-02-28 39 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

很酷。 Zip似乎並不是我最喜歡透露的名字,但至少它很短。當我第一次看到你的答案時,我以爲它是一個下載!歡呼 – Berryl 2010-02-28 20:37:29

+0

誠然,這不是世界上最容易發現的名字。我認爲Eric Lippert提出了這個術語:http://blogs.msdn.com/ericlippert/archive/2009/05/07/zip-me-up.aspx。無論哪種方式,這是一個有用的擴展。 :) – Aaronaught 2010-02-28 20:40:59

+2

這個名字來自功能語言。這就是所謂的,因爲它像拉鍊一樣工作。默認情況下,它應該做一些類似於表單元組的東西,其中第一個元素來自列表1,第二個來自2. – flq 2010-02-28 20:41:53

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中有更多的擴展如Zip嗎? – Berryl 2010-02-28 20:21:08

+0

Zip是Enumerable類中唯一的新方法,但可能有其他地方... – 2010-02-28 20:32:21

相關問題