1

I want to merge the values of multiple dictionaries (3 to be exact) into a list. My current solution uses linq to first combine the dictionaries and then converts the values into a list.

private List<Part> AllParts()
{
    return walls.Concat(floors)
                .Concat(columns)
                .ToDictionary(kvp => kvp.Key, kvp => kvp.Value)
                .Values
                .ToList();
}

Merging the lists first seems redundant. How can I improve this?

JayByte
  • 74
  • 1
  • 9
  • try this solution http://stackoverflow.com/questions/10559367/combine-multiple-dictionaries-into-a-single-dictionary – vivek kv Aug 29 '16 at 07:43

3 Answers3

1

You can simplify this code by concatenating your dictionaries and selecting values without converting to a dictionary:

return walls.Concat(floors)
            .Concat(columns)
            .Select(kvp => kvp.Value)
            .ToList();

It looks like the shortest and most readable solution. You can avoid concatenating your collections by taking values only:

return walls.Values
            .Concat(floors.Values)
            .Concat(columns.Values)
            .ToList();

However, I do not see any readability, maintainability or performance improvements here.

P.S. I assumed that there are no duplicates in your dictionaries. This code will contain duplicated values while ToDictionary approach will throw exceptions on key duplication.

Yeldar Kurmangaliyev
  • 33,467
  • 12
  • 59
  • 101
1

First off, some useful links:

Combine multiple dictionaries into a single dictionary

Combine multiple dictionaries with same key in them into one dictionary with the sum of values

Merging dictionaries in C#

Basically, merging the dictionaries first is a must, but there are more efficient ways than yours to avoid duplicates, such as:

Option 1

var dictionaries = new[] { walls, floors, columns };
var result = dictionaries
  .SelectMany(d => d)
  .GroupBy(
    kvp => kvp.Key,
    (key, kvps) => new { Key = key, Value = kvps.Sum(kvp => kvp.Value) }
  )
  .ToDictionary(x => x.Key, x => x.Value).ToList();
return result;

Works with any number of dictionaries, not just 3.

Option 2

var result = walls.Union(floors).Union(columns)
             .ToDictionary (k => k.Key, v => v.Value).ToList();
return result;

to avoid duplicates:

var result = walls.Concat(floors).Concat(columns).GroupBy(d => d.Key)
             .ToDictionary (d => d.Key, d => d.First().Value).ToList();
Community
  • 1
  • 1
Keyur PATEL
  • 2,299
  • 1
  • 15
  • 41
  • This doesn't really answer the question. Also, as others mentioned, there are ways of merging just the values of dictionaries without taking into account duplicate keys. – JayByte Aug 29 '16 at 13:21
1

Dictionary exposes a property called Values, which is basically a read-only collection of all the values in that Dictionary. This is the simplest way to get all the value when you don't care about the key, and it's the easiest way to combine them:

var allParts = walls.Values
               .Concat(floors.Values)
               .Concat(columns.Values);

This is much simpler, and possibly more performant, than various methods of merging dictionaries, using LINQ queries to convert KeyValuePairs to Parts and so on - you don't care about the Dictionariness here, only the list of values - so treat it as a list of values.

One thing, though, is that this will not strip out duplicate Parts, if any exist. You can do that by using Union() instead of Concat().

Avner Shahar-Kashtan
  • 14,492
  • 3
  • 37
  • 63