我可以在LINQ中获得两个IEnumerables的增量吗?

时间:2010-02-28 19:45:23

标签: c# linq

不是总增量,而是每个元素的增量。这里有一些代码来解释我的意思:

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

3 个答案:

答案 0 :(得分: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);
        }
    }
}

答案 1 :(得分: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);
            }
        }
    }

答案 2 :(得分:1)

post相关,并提供answer