C# Linq merge two dictionaries [duplicate]

2020-06-17 15:25发布

问题:

How to make the following method more functional-linq-style?

    public static Dictionary<T, T> MergeDict<T, T>(Dictionary<T, T> a, Dictionary<T, T> b)
    {
        var e = new Dictionary<T, T>();

        a.Concat(b).ToList().ForEach(pair =>
        {
            e[pair.Key] = pair.Value;
        });

        return e;
    }

回答1:

To continue your duplicate discarding ways, just group up and take a winning item in the group (such as the Last one).

first.Concat(second)
  .GroupBy(kvp => kvp.Key, kvp => kvp.Value)
  .ToDictionary(g => g.Key, g => g.Last());


回答2:

You could use ToDictionary directly:

public static Dictionary<T, T> MergeDict<T, T>(Dictionary<T, T> a, Dictionary<T, T> b)
{
     return a.Concat(b).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
}

Be aware that this will raise an exception in the case of duplicate keys.

If you need to handle duplicate keys, you'll need to decide how you want this to be handled. For example, this will remove duplicates from "b":

public static Dictionary<T, T> MergeDict<T, T>(Dictionary<T, T> a, Dictionary<T, T> b)
{
     return a.Concat(b.Where(kvp => !a.ContainsKey(kvp.Key)).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
}

To get the same behavior as the original, you could go the other way (keeps KeyValuePair values from "b"):

public static Dictionary<T, T> MergeDict<T, T>(Dictionary<T, T> a, Dictionary<T, T> b)
{
     return b.Concat(a.Where(kvp => !b.ContainsKey(kvp.Key)).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
}


回答3:

Perhaps something like this.

public static IDictionary<T, U> Merge<T, U>(this IDictionary<T, U> first, IDictionary<T, U> second)
{
    return first.Concat(second).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
}