web-dev-qa-db-fra.com

Mappez deux listes dans un dictionnaire en C #

Étant donné que deux IEnumerables 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
56
BrunoLM

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);
114
dahlbyk

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 ...)

22
dahlbyk

J'aime cette approche:

var dict =
   Enumerable.Range(0, keys.Length).ToDictionary(i => keys[i], i => values[i]);
10
Todd Menier

Si vous utilisez MoreLINQ , vous pouvez également utiliser sa méthode ToDictionary extension sur la KeyValuePairs 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.

0
Deilan