Объединение словарей на ключевом уровне, а затем на уровне значений - PullRequest
3 голосов
/ 03 сентября 2010

У меня есть два словаря, как

Dictionary<String, String> one = new Dictionary<string, string>
{
    { "A", "1" },
    { "B", "2" },
    { "C", "3" },
    { "D", "4" },
    { "E", "5" },
    { "F", "6" },
    { "G", "7" },
    { "H", "8" }
};

Dictionary<String, String> two = new Dictionary<string, string>
{
    { "A", "1" },
    { "B", "2" },
    { "C", "3" },
    { "E", "4" },
    { "F", "4" },
    { "I", "6" },
    { "J", "10" },
    { "K", "11" }
};

мне нужно объединить два словаря на уровне ключей, а затем на уровне значений и добавить результирующий словарь в новый словарь three, результирующий словарь не должен иметь одинаковые ключи или одинаковые значения, и в этом случае результирующий словарь это как

Dictionary<String, String> three = new Dictionary<string, string>
{
    { "A", "1" },
    { "B", "2" },
    { "C", "3" },
    { "D", "4" },
    { "E", "5" },
    { "F", "6" },
    { "G", "7" },
    { "H", "8" },
    { "J", "10" },
    { "K", "11" }
};

Теперь я использую как

  1. Объединение всех ключей в двух словарях
  2. Создание нового словаря с новыми ключами
  3. удаление значений дубликатов (одинаковые значения)

РЕДАКТИРОВАТЬ : если оба словаря имеют одинаковую пару ключ-значение, мне нужно сохранить пару ключ-значение из первого словаря.

есть ли способ сделать это с помощью LINQ? Заранее спасибо

Ответы [ 4 ]

2 голосов
/ 03 сентября 2010

Один вариант, использующий тот факт, что словарь представляет собой последовательность пар ключ / значение:

var dictionary = dictionary1.Concat(dictionary2)
                            .ToLookup(pair => pair.Key, pair => pair.Value)
                            .ToDictionary(x => x.Key, x => x.First());

Это не очень эффективно, по общему признанию (поскольку это по существу создает хэш-таблицу дважды), но я считаю,это будет работать.

1 голос
/ 03 сентября 2010
class StringKeyValuePairEqualityComparer : IEqualityComparer<KeyValuePair<string, string>>
{
    public bool Equals(KeyValuePair<string, string> x, KeyValuePair<string, string> y)
    {
        return x.Key == y.Key;
    }

    public int GetHashCode(KeyValuePair<string, string> obj)
    {
        return obj.Key.GetHashCode();
    }
}

var three = Enumerable.Concat(one, two)
                .Distinct(new StringKeyValuePairEqualityComparer())
                .ToDictionary(p => p.Key, p => p.Value);

int count = three.Keys.Count; // 11
1 голос
/ 03 сентября 2010

Метод linq-only будет заключаться в объединении двух словарей и объединении результирующей последовательности ключей / значений в один результат. Это заменит значения для любых клавиш в dict2, которые также находятся в dict1:

var dict3 = dict2.Concat(dict1)
    .Aggregate(new Dictionary<string, string>(), (d, kvp) => {
        d[kvp.Key] = kvp.Value;
        return d;
    });
1 голос
/ 03 сентября 2010
var three = new Dictionary<string, string>();
foreach(var kvp in two.Concat(one))
  three[kvp.Key] = kvp.Value;

Это довольно эффективно, но я не уверен, что вы хотите именно такой вывод;формулировка проблемы недостаточно ясна.

РЕДАКТИРОВАТЬ : Если вы хотите впоследствии удалить дубликаты значений из three:

var keysWithDuplicateValues = three.ToLookup(kvp => kvp.Value, kvp => kvp.Key)
                                   .SelectMany(group => group.Skip(1))
                                   .ToList();

foreach(var key in keysWithDuplicateValues)
   three.Remove(key);   

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...