Wenn ich zwei IEnumerable
s der gleichen Größe habe, wie kann ich es mit Linq in eine Dictionary
konvertieren?
IEnumerable<string> keys = new List<string>() { "A", "B", "C" };
IEnumerable<string> values = new List<string>() { "Val A", "Val B", "Val C" };
var dictionary = /* Linq ? */;
Und der erwartete Output ist:
A: Val A
B: Val B
C: Val C
Ich frage mich, ob es einen einfachen Weg gibt, dies zu erreichen.
Und sollte ich mir Sorgen um die Leistung machen? Was ist, wenn ich große Sammlungen habe?
Ich weiß nicht, ob es einen einfacheren Weg gibt, derzeit mache ich Folgendes:
Ich habe eine Erweiterungsmethode, die die IEnumerable
-Schleife durchläuft und mir das Element und die Indexnummer zur Verfügung stellt.
public static class Ext
{
public static void Each<T>(this IEnumerable els, Action<T, int> a)
{
int i = 0;
foreach (T e in els)
{
a(e, i++);
}
}
}
Und ich habe eine Methode, die eine der Enumerables in einer Schleife durchläuft und mit dem Index das entsprechende Element auf der anderen Enumerable abruft.
public static Dictionary<TKey, TValue> Merge<TKey, TValue>(IEnumerable<TKey> keys, IEnumerable<TValue> values)
{
var dic = new Dictionary<TKey, TValue>();
keys.Each<TKey>((x, i) =>
{
dic.Add(x, values.ElementAt(i));
});
return dic;
}
Dann benutze ich es wie:
IEnumerable<string> keys = new List<string>() { "A", "B", "C" };
IEnumerable<string> values = new List<string>() { "Val A", "Val B", "Val C" };
var dic = Util.Merge(keys, values);
Und die Ausgabe ist korrekt:
A: Val A
B: Val B
C: Val C
Mit .NET 4.0 (oder der Version 3.5 von System.Interactive von Rx) können Sie Zip()
verwenden:
var dic = keys.Zip(values, (k, v) => new { k, v })
.ToDictionary(x => x.k, x => x.v);
Basierend auf Ihrer Idee enthält LINQ eine Überladung von Select()
, die den Index bereitstellt. Kombiniert mit der Tatsache, dass values
den Zugriff über den Index unterstützt, könnte man Folgendes tun:
var dic = keys.Select((k, i) => new { k, v = values[i] })
.ToDictionary(x => x.k, x => x.v);
(Wenn values
als List<string>
beibehalten wird, heißt das ...)
Ich mag diesen Ansatz:
var dict =
Enumerable.Range(0, keys.Length).ToDictionary(i => keys[i], i => values[i]);
Wenn Sie MoreLINQ verwenden, können Sie auch die Erweiterungsmethode ToDictionary für zuvor erstellte KeyValuePair
s verwenden:
var dict = Enumerable
.Zip(keys, values, (key, value) => KeyValuePair.Create(key, value))
.ToDictionary();
Es sollte auch beachtet werden, dass die Verwendung der Erweiterungsmethode Zip
für Eingabesammlungen unterschiedlicher Länge sicher ist.