Based on Question Update:
This is very complex (at least it was for me). I showed the steps and also i put each LINQ inside parenthesis which do the part of that job.
1) You have to join two lists. (ListdicA.Concat(ListdicB))
2) Group all Dictionaries by Value of Type1 key in each dictionaries.(GroupBy(x => x["Type1"]))
3) Unwrap all Items IGrouping<string,Dictionary<string,string>> to KeyValuePair<string,string> (SelectMany(y => y))
4) Again Group key value pairs by Key so that you join values of same keys together (GroupBy(y => y.Key))
5) Unwrap IGrouping<string,KeyValuePair<string,string>> into IEnumerable<KeyValuePair<string,List<string>>> (Select(y => new KeyValuePair<string, List<string>>(y.Key, y.Select(z => z.Value).ToList())))
6) Convert IEnumerable<IEnumerable<KeyValuePair<string,List<string>>>> into IEnumerable<Dictionary<string,List<string>>> (Select(x => x.ToDictionary(y => y.Key, y => y.Value)))
7) Finally Convert IEnumerable<Dictionary<string,List<string>>> into List<Dictionary<string, List<string>>> (ToList())
string groupby = "Type1";
List<Dictionary<string, List<string>>> result =
ListdicA.Concat(ListdicB).GroupBy(x => x[groupby]).Select(x =>
x.SelectMany(y => y) // Put .Distinct() here to remove duplicates.(optional)
.GroupBy(y => y.Key).Select(y => new KeyValuePair<string, List<string>>(y.Key, y.Select(z => z.Value).ToList())))
.Select(x => x.ToDictionary(y => y.Key, y => y.Value)).ToList();
foreach (var d in result)
{
foreach (var k in d)
{
Console.Write(k.Key + " : ");
foreach (var l in k.Value)
{
Console.Write(l + " ");
}
Console.WriteLine();
}
}
Outputs
Type1 1 1
Type2 A C
Type3 X X
Type1 2 2
Type2 B D
Type3 Y Z
As I noted in comment (inside code) if you remove that comment and put .Distinct() right there it will remove duplicates
List<Dictionary<string, List<string>>> result =
ListdicA.Concat(ListdicB).GroupBy(x => x[groupby]).Select(x => x.SelectMany(y => y)
.Distinct().GroupBy(y => y.Key)
.Select(y => new KeyValuePair<string, List<string>>(y.Key, y.Select(z => z.Value).ToList())))
.Select(x => x.ToDictionary(y => y.Key, y => y.Value)).ToList();
will output.
Type1 1
Type2 A C
Type3 X
Type1 2
Type2 B D
Type3 Y Z
If you dont want to loose X then you need a custom Distinct. You will need this class. (linq was taken and edited from here)
public static class SomeMoreLinq
{
public static IEnumerable<TSource> DistinctIf<TSource>
(this IEnumerable<TSource> source, Func<TSource, bool> keySelector)
{
HashSet<TSource> seenKeys = new HashSet<TSource>();
foreach (TSource element in source)
{
if (seenKeys.Add(element) || !keySelector(element))
{
yield return element;
}
}
}
}
And then use it in your query.
List<Dictionary<string, List<string>>> result =
ListdicA.Concat(ListdicB).GroupBy(x => x[groupby]).Select( x => x.SelectMany(y => y)
.DistinctIf(y => y.Key == groupby).GroupBy(y => y.Key)
.Select(y => new KeyValuePair<string, List<string>>(y.Key, y.Select(z => z.Value).ToList())))
.Select(x => x.ToDictionary(y => y.Key, y => y.Value)).ToList();
will output.
Type1 1
Type2 A C
Type3 X X
Type1 2
Type2 B D
Type3 Y Z
If you have any questions feel free to ask.
While this completely melted my mind but it was a good practice!.