Linq - wandeln einen ILookup in einer anderen ILookup
Frage
Dies sollte einfach sein, aber ich kann eine gute Art und Weise nicht denken, es zu tun. Wie kann ein ILookup in einer anderen ILookup verwandeln? Zum Beispiel, wie würden Sie kopieren / Klon ein ILookup, eine andere ILookup mit den gleichen Schlüsseln und gleichen Gruppen produzieren?
Hier ist mein lahmer Versuch:
static ILookup<TKey, TValue> Copy<TKey, TValue>(ILookup<TKey, TValue> lookup)
{
return lookup
.ToDictionary(
grouping => grouping.Key,
grouping => grouping.ToArray())
.SelectMany(pair =>
pair
.Value
.Select(value =>
new KeyValuePair<TKey, TValue>(pair.Key, value)))
.ToLookup(pair => pair.Key, pair => pair.Value);
}
Kann jemand dies verbessern?
- Brian
Lösung
Ist das tun, was Sie wollen?
static ILookup<TKey, TValue> Copy<TKey, TValue>(ILookup<TKey, TValue> lookup)
{
return lookup.
SelectMany(g => g,
(g, v) => new KeyValuePair<TKey, TValue>(g.Key, v)).
ToLookup(kvp => kvp.Key, kvp => kvp.Value);
}
Natürlich, wenn Sie die Werte irgendwie umwandeln wollen, vielleicht wollen Sie etwas wie folgt aus:
static ILookup<TKey, TValueOut> Transform<TKey, TValue, TValueOut>(
ILookup<TKey, TValue> lookup,
Func<TValue, TValueOut> selector)
{
return lookup.
SelectMany(g => g,
(g, v) => new KeyValuePair<TKey, TValueOut>(g.Key, selector(v))).
ToLookup(kvp => kvp.Key, kvp => kvp.Value);
}
Hinweis, dass dieses Verfahren in einem Zwischenwert KeyValuePair
hält, die einen Wert ein, wobei auf dem Stapel abgelegt wird und somit keine Zwischenspeicherzuordnungen erfordern. Ich Profil einen Test, der eine Lookup<int,int>
mit 100 Tasten erzeugt, die jeweils 10.000 Stück (für insgesamt 1.000.000).
- Erstellen der
Lookup
hat 1610 Zuweisungen. - Kopiert es mit meiner Methode macht 1712 Zuweisungen (alle Zuweisungen erforderlich, um es zu schaffen und einen für jeden Teilnehmer in dem
SelectMany
Anruf und ein für den Enumerator für jede Taste). - es mit anonymen Kopieren von Objekten statt
KeyValuePair
tut 1.001.712 Zuweisungen (alle die Zuweisungen erforderlich plus eins für jedes Element zu kopieren).
CPU-weise, sogar mit 100.000 Elemente pro Schlüssel in der Lookup
Leistung zwischen den beiden Kopierverfahren waren identisch. Mit 1.000.000 Elementen pro Schlüssel war die Leistung unterschiedlich zwischen den beiden Methoden:
- 5.1 sec erstellen
- 5.9 sec mit
KeyValuePair
kopieren - 6.3 sec mit anonym kopieren Objekte
Andere Tipps
Wie wäre es damit:
return lookup
.SelectMany (grp => grp, (grp, item) => new { grp.Key, item})
.ToLookup (x => x.Key, x => x.item);