c#将多个词典合并为一个

时间:2017-05-23 16:13:46

标签: c# dictionary

首先,我想提一下,我几天前才开始学习C#,所以我对它的了解有限。

我正在将具有相同类型键值对的多个词典合并为一个词典。

以下是我的方法,它可以处理重复项

 var result = dict1.Concat(dict2).GroupBy(d => d.Key)
              .ToDictionary(d => d.Key, d => d.First().Value);

            result = result.Concat(dict3).GroupBy(d => d.Key)
                .ToDictionary(d => d.Key, d => d.First().Value);

            result = result.Concat(dict4).GroupBy(d => d.Key)
                .ToDictionary(d => d.Key, d => d.First().Value);

            result = result.Concat(dict5).GroupBy(d => d.Key)
    .ToDictionary(d => d.Key, d => d.First().Value); 

我想知道是否有一种有效的方法来合并具有相同数据类型的键值对的多个词典。

2 个答案:

答案 0 :(得分:9)

由于字典实现了IEnumerable<KeyValuePair<TKey, TValue>>,您只需编写:

var result = dict1
    .Concat(dict2)
    .Concat(dict3)
    .Concat(dict4)
    .Concat(dict5)
    .ToDictionary(e => e.Key, e => e.Value);

这假设没有重复的密钥。

如果有重复的键,您可以获得每个键的第一个值

result = dict1
    .Concat(dict2)
    .Concat(dict3)
    .Concat(dict4)
    .Concat(dict5)
    .GroupBy(e => e.Key)
    .ToDictionary(g => g.Key, g => g.First().Value);

可以想到其他变体,例如保持最大/最小值等。

如果存在具有不同值的重复键,您还可以创建值列表字典

Dictionary<TKey, List<TValue>> result = dict1
    .Concat(dict2)
    .Concat(dict3)
    .Concat(dict4)
    .Concat(dict5)
    .GroupBy(e => e.Key, e => e.Value)
    .ToDictionary(g => g.Key, v => v.ToList());

您可以将List<T>插入HashSet<T>,而不是创建Union值,而只保留唯一值。

如果重复键的值始终相同,则只需使用Concat代替var result = dict1 .Union(dict2) .Union(dict3) .Union(dict4) .Union(dict5) .ToDictionary(e => e.Key, e => e.Value);

Dictionary<TKey, List<TValue>> result = dict1
    .Union(dict2)
    .Union(dict3)
    .Union(dict4)
    .Union(dict5)
    .GroupBy(e => e.Key, e => e.Value)
    .ToDictionary(g => g.Key, v => v.ToList());

Union生成两个序列的集合。 Concat连接两个序列。

最后,您可以结合前面两种方法并丢弃相等的键/值对,但每个键保留一个不同值的列表:

{{1}}

这些示例表明,确切了解输入数据的形状(唯一/非唯一键和键值对)以及您期望的结果类型非常重要。

另一种方法是让您的不同方法返回列表或枚举而不是字典,并在最后将这些集合合并到字典中。这样会更有效。

答案 1 :(得分:2)

虽然它没有使用任何漂亮的Linq,但我认为以下内容会更有效率。它只创建一个附加字典,这就是结果。它的大小最初是为了不会增长。此外,插入的数量将与结果Dictionary中的元素数量完全相同。

我认为这比创建多个中间词典或其他集合更有效,或者以导致新词典或中间词典必须经历多个增长调整大小的方式处理。在中间foreach,我不知道检查dict1result ContainsKey是否更有效。我检查了dict1,因为无需检查result哪个dict2会有越来越多的值,我们知道dict2中没有关键字dict2 1}}不止一次。

var result = new Dictionary<MyKeyType, MyValueType>(dict1.Count + dict2.Count + dict3.Count
    + dict4.Count + dict5.Count);
foreach(var pair in dict1) {
    result.Add(pair.Key, pair.Value);
}
foreach(var pair in dict2) {
    if (!dict1.ContainsKey(pair.Key)) result.Add(pair.Key, pair.Value);
}
foreach(var pair in dict3) {
    if (!result.ContainsKey(pair.Key)) result.Add(pair.Key, pair.Value);
}
foreach(var pair in dict4) {
    if (!result.ContainsKey(pair.Key)) result.Add(pair.Key, pair.Value);
}
foreach(var pair in dict5) {
    if (!result.ContainsKey(pair.Key)) result.Add(pair.Key, pair.Value);
}

在一个定时测试中,有5个大词典,它们之间大多有唯一的键,它就像这样(以毫秒为单位):

    您的代码
  • 1037毫秒
  • 使用Linq的其他答案中的中间代码块
  • 357 ms
  • 784 ms ,使用Linq的其他答案中的第三个代码块
  • 43 ms ,使用foreach上面的代码

如果某个键位于多个词典中,则第一个值是使用的值,因为您没有指定任何特定的方式来处理这种情况。