views:

64

answers:

3

I have an object that looks like this:

class Model
{
   public string Category {get;set;}
   public string Description {get;set;}
}

Currently I am getting the whole list of those objects with Linq, and then manually setting up a dictionary, like this:

   List<Model> models = //get list from repository and then with linq order them by category and description

Dictionary<string, List<Model>> dict= new Dictionary<string, List<Model>>();

            foreach (var m in models)            {
                if (dict.ContainsKey(m.Category))
                {
                    dict[m.Category].Add(m);
                }
                else
                {
                    dict.Add(m.Category, new List<Model> { m });
                }    
            }

this way I can access all of the models of a certain category by using the keys.

Is there a way to generate the dictionary straight with a LINQ query?

Thanks!

+1  A: 

yeah there's a way to that, but to get this done you'll need to group them first (to avoid duplicate keys):

var dict = (from model in models
            group model by model.Category into g
            select g).ToDictionary(x => x.Key, x => x.ToList());

(While you're at it, I wonder what the performance of this and the .ContainsKey() way is)

Sander Rijken
A: 

You can use Aggregate() to hide the foreach logic, but as the OP to whom I last suggested that said, it's a loop in Linq clothing.

What about:

var myDictionary = (from m in models
                   group m by m.Category into theGroup
                   select new {Key = m.Category, Value = theGroup.ToList()))
                   .ToDictionary(x=>x.Key, x=>x.Value);
KeithS
+5  A: 

Have you seen the Lookup class? (msdn)

You can create it with a call to the Enumerable.ToLookup() method (msdn)

It's basically exactly what you want here, and handles the dupe keys.

Andrew Barber
+1 for simplicity.
Callum Rogers
Look at the info on the Lookup class; you need to enumerate it slightly differently since it is a special collection within a collection.
Andrew Barber