Étant donné que deux IEnumerable
s de la même taille, comment puis-je le convertir en Dictionary
en utilisant Linq?
IEnumerable<string> keys = new List<string>() { "A", "B", "C" };
IEnumerable<string> values = new List<string>() { "Val A", "Val B", "Val C" };
var dictionary = /* Linq ? */;
Et le résultat attendu est:
A: Val A
B: Val B
C: Val C
Je me demande s'il existe un moyen simple d'y parvenir.
Et devrais-je m'inquiéter de la performance? Et si j'ai de grandes collections?
Je ne fais pas s'il y a un moyen plus facile de le faire, actuellement je fais comme ça:
J'ai une méthode d'extension qui bouclera la IEnumerable
en me fournissant l'élément et le numéro d'index.
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++);
}
}
}
Et j'ai une méthode qui va boucler l'un des Enumerables et avec l'index, récupérer l'élément équivalent sur l'autre Enumerable.
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;
}
Ensuite, je l'utilise comme:
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);
Et le résultat est correct:
A: Val A
B: Val B
C: Val C
Avec .NET 4.0 (ou la version 3.5 de System.Interactive de Rx), vous pouvez utiliser Zip()
:
var dic = keys.Zip(values, (k, v) => new { k, v })
.ToDictionary(x => x.k, x => x.v);
Ou, selon votre idée, LINQ inclut une surcharge de Select()
qui fournit l'index. Combiné au fait que values
prend en charge l’accès par index, on peut procéder comme suit:
var dic = keys.Select((k, i) => new { k, v = values[i] })
.ToDictionary(x => x.k, x => x.v);
(Si values
est conservé en tant que List<string>
, c’est ...)
J'aime cette approche:
var dict =
Enumerable.Range(0, keys.Length).ToDictionary(i => keys[i], i => values[i]);
Si vous utilisez MoreLINQ , vous pouvez également utiliser sa méthode ToDictionary extension sur la KeyValuePair
s créée précédemment:
var dict = Enumerable
.Zip(keys, values, (key, value) => KeyValuePair.Create(key, value))
.ToDictionary();
Il convient également de noter que l’utilisation de la méthode d’extension Zip
est sans danger par rapport aux collections d’entrée de différentes longueurs.