Reputation: 33
I need to combine 2 dictionary. they have the same key (KKK) with different values:
Dictionary<string, string> dic1 = ...Load***();
Dictionary<string, string> dic2 = ...Load***();
dic1:
...
[29] {[RCP, 555501001]}
[30] {[KKK, 04611105012042000120]}
...
dic2:
...
[49] {[SUM, 85737]}
[50] {[KKK, 04611701040040000180]}
...
Union:
Dictionary<string, string> dicUnion= dic1.Union(dic2).OrderBy(k => k.Key).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
result:
ThrowArgumentException: The item with the same key has already been added.
I have connect values with the same key in union Dictionary:
...
[29] {[RCP, "555501001"]}
[30] {[KKK, "04611105012042000120 04611701040040000180"]}
[31] {[SUM, "85737"]}
...
Upvotes: 3
Views: 296
Reputation: 460068
If you really want to use LINQ in this case(i'd prefer a loop):
var dicUnion = dic1.Concat(dic2)
.GroupBy(kv => kv.Key)
.ToDictionary(g => g.Key, g => String.Join(" ", g.Select(kv => kv.Value)));
This will merge both dictionaries but don't care about common keys or different values.
I need to combine 2 dictionary, they have the same key (KKK) with different values
Ok, if you only want to create a dictionary of common keys:
var union = from kv1 in dic1
join kv2 in dic2
on kv1.Key equals kv2.Key into keyGroup
where keyGroup.Any()
select new KeyValuePair<string, string>(kv1.Key, string.Join(" ", keyGroup.Select(kv => kv.Value)));
Dictionary<string, string> dicUnion = union.ToDictionary(kv => kv.Key, kv => kv.Value);
But instead of concatenating values which have the same key in both dictionaries, i'd use a different approach. Use a Lookup<TKey, TValue>
. For example:
var keyLookup = dic1.Concat(dic2).ToLookup(kv => kv.Key, kv => kv.Value);
Now you can do wahtever you want with the values, f.e. create a List<string>
:
List<string> values = keyLookup["KKK"].ToList();
Upvotes: 4
Reputation: 4981
If you want to connect ONLY values with the same key, you can use IEnumerable.Join
method like this:
var res = dic1.Join(dic2, o1 => o1.Key, o2 => o2.Key, (o1, o2) => new { o1.Key, Value1 = o1.Value, Value2 = o2.Value});
The arguments are the second IEnumerable
, key selectors and result selector. In my snippet I create anonymous class but you can create whatever structure you want. The result is again IEnumerable
, you can either iterate on or use its ToList()
, ToArray()
, etc method.
EDIT: after reading comments to other posts I understand you want to get something like this:
dic1.Concat(dic2)
.ToLookup(o => o.Key, o => o.Value)
.ToDictionary(o => o.Key, o => string.Join(" ", o.Distinct()))
Upvotes: 0
Reputation: 45947
I'd use a simple loop to add / append items
Dictionary<string, string> dicUnion = new Dictionary<string, string>(dic1);
foreach(var item in dic2)
{
if(dicUnion.ContainsKey(item.Key))
{
dicUnion[item.Key] += " " + item.Value;
}
else
{
dicUnion.Add(item.Key, item.Value);
}
}
Upvotes: 4
Reputation: 13146
Just try like this;
var intersectedItems = dic1.Where(x => dic2.ContainsKey(x.Key)).Select(x => new
{
Key = x.Key,
Value = x.Value + " " + dic2[x.Key]
}).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
var dicUnion = dic1.Where(x => !intersectedItems.ContainsKey(x.Key))
.Union(dic2.Where(x => !intersectedItems.ContainsKey(x.Key)))
.Union(intersectedItems).OrderBy(k => k.Key)
.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
Upvotes: 1