5

I've got a query that returns something of the following format:

{ "tesla", "model s" }
{ "tesla", "roadster" }
{ "honda", "civic" }
{ "honda", "accord" }

and I'd like to convert that to a dictionary of <string, string[]> like so:

{ "tesla" : ["model s", "roadster"],  "honda" : ["civic", "accord"] }

I've tried with this:

var result = query.Select(q => new { q.Manufacturer, q.Car}).Distinct().ToDictionary(q => q.Manufacturer.ToString(), q => q.Car.ToArray()); 

but so far I am not having any luck. I think what this is doing is actually trying to add individual items like "tesla" : ["model s"] and "tesla" : ["roadster"] and that's why it's failing ... any easy way to accomplish what I am trying to do in LINQ?

p.s.w.g
  • 146,324
  • 30
  • 291
  • 331
Brian D
  • 9,863
  • 18
  • 61
  • 96

4 Answers4

3

You would need to group each item by the key first, then construct the dictionary:

result = query.Select(q => new { q.Manufacturer, q.Car}).Distinct()
              .GroupBy(q => q.Manufacturer)
              .ToDictionary(g => g.Key, 
                            g => g.Select(q => q.Car).ToArray());

Of course, an ILookup<string, string> much easier:

result = query.Select(q => new { q.Manufacturer, q.Car }).Distinct()
              .ToLookup(q => q.Manufacturer, q => q.Car);
p.s.w.g
  • 146,324
  • 30
  • 291
  • 331
3

You're looking for ToLookup if you would like the results to be grouped into a dictionary-like object:

var result = query.Select(q => new { q.Manufacturer, q.Car})
                  .Distinct()
                  .ToLookup(q => q.Manufacturer.ToString(), q => q.Car);

Otherwise you will have to group the results first:

var result = query.Select(q => new { q.Manufacturer, q.Car })
                  .Distinct()
                  .GroupBy(q => q.Manufacturer)
                  .ToDictionary(gg => gg.Key,
                                gg => gg.Select(q => q.Car).ToArray());
user7116
  • 63,008
  • 17
  • 141
  • 172
1

What you want is GroupBy(), followed by ToDictionary().

Example:

var result = query.GroupBy(q => q.Manufacturer).ToDictionary(q => q.Key, q => q.Value.ToArray());

What GroupBy() does is group all the elements that have the same matching key selector. So when you tell it to GroupBy(q => q.Manufacturer), all the elements that have the same Manufacturer will be grouped together as IEnumerable<T>.

rossipedia
  • 56,800
  • 10
  • 90
  • 93
0

Use ToLookup:

var table = pairs.ToLookup(kvp => kvp.Key, kvp => kvp.Value);

foreach(var i in table["tesla"])
   Console.WriteLine(i);
sehe
  • 374,641
  • 47
  • 450
  • 633