Сопоставить два списка в словарь в C # - PullRequest
61 голосов
/ 28 октября 2010

Учитывая два IEnumerable с одинакового размера, как я могу преобразовать его в Dictionary , используя 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 ? */;

И ожидаемый результат:

A: Val A
B: Val B
C: Val C

Интересно, есть ли какой-нибудь простой способ добиться этого?

И стоит ли беспокоиться о производительности? Что делать, если у меня большие коллекции?


Нет, если есть более простой способ сделать это, в настоящее время я делаю так:

У меня есть метод Extension, который будет зацикливать IEnumerable, предоставляя мне элемент и порядковый номер.

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

И у меня есть метод, который зациклит один из перечисляемых и с помощью индекса извлекает эквивалентный элемент из другого перечисляемого.

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

Тогда я использую это как:

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

И вывод правильный:

A: Val A
B: Val B
C: Val C

Ответы [ 4 ]

119 голосов
/ 28 октября 2010

. .NET 4.0 (или версия System.Interactive от Rx 3.5) позволяет использовать Zip():

var dic = keys.Zip(values, (k, v) => new { k, v })
              .ToDictionary(x => x.k, x => x.v);
23 голосов
/ 28 октября 2010

Или, согласно вашей идее, LINQ включает перегрузку Select(), которая обеспечивает индекс.В сочетании с тем, что values поддерживает доступ по индексу, можно сделать следующее:

var dic = keys.Select((k, i) => new { k, v = values[i] })
              .ToDictionary(x => x.k, x => x.v);

(если values сохраняется как List<string>, то есть ...)

11 голосов
/ 12 июня 2014

Мне нравится такой подход:

var dict =
   Enumerable.Range(0, keys.Length).ToDictionary(i => keys[i], i => values[i]);
0 голосов
/ 01 февраля 2018

Если вы используете MoreLINQ , вы также можете использовать его ToDictionary метод расширения для ранее созданных KeyValuePair s:

var dict = Enumerable
    .Zip(keys, values, (key, value) => KeyValuePair.Create(key, value))
    .ToDictionary();

Это также следует отметитьчто метод расширения Zip безопасен для входных наборов различной длины.

...