8 Stimmen

Kann ich das Delta von zwei IEnumerables in LINQ erhalten?

Nicht das Gesamtdelta, sondern das Delta der einzelnen Elemente. Hier ist etwas Code, um zu erklären, was ich meine:

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

Es ist die letzten vier Zeilen des Codes, die scheinen, wie es eine elegantere Möglichkeit, in LINQ irgendwie zu tun sein könnte.

Zum Wohl,
Berryl

7voto

Aaronaught Punkte 118136

Was Sie wollen, ist die Aufzählbar.Zip Erweiterungsmethode.

Ein Beispiel wäre die Verwendung:

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

Beachten Sie, dass dies neu in .NET 4.0 ist. In .NET 3.5 mussten Sie Ihre eigene Erweiterung schreiben. Etwas wie dies:

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

5voto

Thomas Levesque Punkte 277723

Wie Aaronaught in seiner Antwort sagte, sollten Sie die Zip Methode; allerdings ist sie in .NET 3.5 nicht verfügbar, nur in 4.0. Hier ist eine benutzerdefinierte Implementierung :

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

1voto

AxelEckenberger Punkte 16238

この Beitrag ist verwandt und bietet eine Antwort .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X