Oskar
Oskar

Reputation: 2083

Add objects to a List nested inside a Dictionary using LINQ extensions

I have Dictionary<T, T> that contains a key (that represents a category) with an empty List<T> as value:

Dictionary<string, List<IMyObject>> myObjects;

Each pair looks something like this:

{ firstCategory, new List<IMyObject>> }

I now have a List<T> of IMyObject's:

List<IMyObject> myObjectsUnsorted;

I want to loop through myObjectsUnsorted and add to the correct List<T>

foreach (var myObject in myObjectsUnsorted)
{
    myObjects[myObject.Category].Add(myObject);
}

How can I do this without a loop? For example with a LINQ extension method? My other objects in this example is created with .Select() but that dosen't really fit the bill in this last foreach.

Upvotes: 1

Views: 896

Answers (2)

Jon Skeet
Jon Skeet

Reputation: 1500873

I would suggest using a lookup instead:

ILookup<string, IMyObject> lookup = myObjectsUnsorted.ToLookup(t => t.Category);

ILookup<,> is precisely designed to be a "multiple values per key" dictionary. As well as being incredibly simple to construct, it has the benefit that if you look up a key which isn't represented, you get an empty sequence back instead of an exception. So you can always just write:

foreach (var item in lookup[key])
{
    ...
}

As opposed to:

IList<MyObject> list;
if (dictionary.TryGetValue(key, out list))
{
    foreach (var item in list)
    {
        ...
    }
}

Note that a lookup is immutable in that you can't change which items are in it after construction. (If the items are mutable reference types, you can modify the objects themselves of course...) That can be a blessing or a curse, depending on your situation...

Upvotes: 8

slawekwin
slawekwin

Reputation: 6310

You can also use GroupBy like so:

var dict = myObjectsUnsorted.GroupBy(q => q.Category)
                            .ToDictionary(q => q.Key, w => new List<IMyObject>(w));

Upvotes: 2

Related Questions