如何加入两个字典集合linq查询

时间:2017-08-15 08:19:06

标签: c# linq

我的第一个数据集是这样的:

IEnumerable<Dictionary<string, object>> firstSourceData;

项目是这样的:

new Dictionary<string, object>
{
    ["id"] = 1,
    ["name"] = "some",
    ["age"] = 30
}

我的第二个数据是另一个字典集:

IEnumerable<Dictionary<string, object>> secondSourceData;

项目是这样的:

new Dictionary<string, object>
{
    ["id"] = 1,
    ["sales"] = 58,
    ["age"] = 30
}

这两个数据来自不同的来源,我将创建一个不包含重复值的字典集合。只有Id键是Dictianaries的标准,其他属性可能会改变。

IEnumerable<Dictionary<string, object>> joined;

new Dictionary<string, object>
{
    ["id"] = 1,
    ["sales"] = 58,
    ["name"] = "some",
    ["age"] = 30
},

如何使用LINQ lambda表达式执行此操作? (如果源长差异,是否有任何问题)

3 个答案:

答案 0 :(得分:1)

这是你要做的事情:

  • 合并两个词典集合。
  • 按&#34; id&#34;分组项目键值。
  • 对于每个组,您有多个词典,因此请使用SelectMany展平,然后使用GroupBy键。现在您可以重新创建词典 - ToDictionary。请注意,您可能需要重复键,这就是嵌套GroupBy和值选择所需的键的原因。我刚刚使用了FirstOrDefault

所以:

var result = firstSourceData.Concat(secondSourceData)
                .GroupBy(item => item["id"])
                .Select(group => group.SelectMany(item => item)
                                      .GroupBy(item => item.Key)
                                      .ToDictionary(key => key.Key, 
                                                    value => value.FirstOrDefault().Value));

结果如下:

new Dictionary<string, object>
{
    ["id"] = 1,
    ["sales"] = 58,
    ["name"] = "some",
    ["age"] = 30
},
new Dictionary<string, object>
{
    ["id"] = 2,
    ["sales"] = 58,
    ["age"] = 30
}

对于此测试用例:

var firstSourceData = new List<Dictionary<string, object>>
{
    new Dictionary<string, object>
    {
        ["id"] = 1,
        ["sales"] = 58,
        ["age"] = 30
    },
    new Dictionary<string, object>
    {
        ["id"] = 2,
        ["sales"] = 58,
        ["age"] = 30
    }
};

var secondSourceData = new List<Dictionary<string, object>>
{
    new Dictionary<string, object>
    {
        ["id"] = 1,
        ["name"] = "some",
        ["age"] = 30
    }
};

答案 1 :(得分:0)

您可以像这样使用Join

from dict1 in firstSourceData
join dict2 in secondSourceData
on dict1["id"] equals dict2["id"]
select dict1.Concat(                                      //concatenates 2 dictionaries together
          dict2.Where(kv => !dict1.ContainsKey(kv.Key))   //chooses non-repeating keys
       ).ToDictionary(kv => kv.Key, kv => kv.Value)       //gets a new dictionary from that

如果源的长度不同join,则只会选择这些词典,其id位于第一个源中。如果您想获得所有id,无论您是否拥有来自这两个来源的数据,都可以使用DefaultIfEmpty

from dict1 in firstSourceData
join tempDict2 in secondSourceData
on dict1["id"] equals tempDict2["id"] into joined
from dict2 in joined.DefaultIfEmpty(new Dictionary<string, object>()) //make a new dictionary if there's none
select dict1.Concat(
          dict2.Where(kv => !dict1.ContainsKey(kv.Key))
       ).ToDictionary(kv => kv.Key, kv => kv.Value)

如果你想要id的两个词典,请参阅this问题。

答案 2 :(得分:-1)

你可以做联盟:

Dictionary<string,object> dict1 = new Dictionary<string, object>();
        dict1.Add("id", 1);
        dict1.Add("name", "Some");
        dict1.Add("age", 30);

        Dictionary<string, object> dict2 = new Dictionary<string, object>();
        dict2.Add("id", 1);
        dict2.Add("sales", 58);
        dict2.Add("age", 30);

        Dictionary<string, object> dict3 = new Dictionary<string, object>();
        dict3 = dict1.Union(dict2).ToDictionary(c => c.Key, c => c.Value);

结果值为:

[0] = {[id, 1]}
[1] = {[name, Some]}
[2] = {[age, 30]}
[3] = {[sales, 58]}