2017-08-15 56 views
3

我的第一個數據收集是這樣的:如何連接兩個字典收藏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表達式來做這件事? (而且是沒有任何問題,如果源長度差)

+0

所以你要加入b y id? –

+0

是按ID加入的。 – barteloma

+0

@Bookmaster:每個字典都包含id-key? –

回答

1

這是你在找什麼做:

  • 合併詞典的兩個集合。
  • 按「id」鍵值分組項目。
  • 對於每個組你有多個字典,所以使用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

'.ToDictionary(key => key.Key,value => value.FirstOrDefault()。Value)'爲我工作。謝謝 – barteloma

+0

@bookmarker - ops true :)否則值是'KeyValuePair '。更正 –

+0

我們可以做到這一點,而不使用身份證密鑰。你可以加入所有,無重複?所以所有的屬性都會插入到新的字典中。 – barteloma

-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]} 
+2

不是'字典<字符串,對象>'它的集合'IEnumerabl <字典<字符串,對象>>' – barteloma

-1

concat

IEnumerable<Dictionary<string, object>> joined; 

joined= firstSSourceData.Concat(secondSourceData.Where(a => !firstSSourceData.ContainsKey(a.Key))); 
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 s在第一個來源。如果你想獲得的所有id S,你無論有兩個來源的數據,你可以使用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 s請參閱this問題。

+0

郵編不通過Id,但索引加入。 OP想要一個扁平版本,其中集合包含每個id的字典以及屬於該id的所有收集的屬性,並在所有字典中找到。 –

+0

好吧,op沒有提到這樣的東西:) –

+0

但你做出了從未提及過的假設,OP剛纔說過他希望每個id都有一個字典,它也包含所有其他「屬性」(鍵值對)屬於該ID並且從兩個序列中的所有字典中收集。唯一靜態的是每個字典都包含id-key。 –