Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Coercing a LINQ result list of KeyValuePair into a Dictionary - Missing the Concept

I wanted to write this LINQ statement:

Dictionary<int, ItemBO> result = ( Dictionary<int, ItemBO> )
    ( from item in originalResults where item.Value.SomeCriteria == true
    select item );

originalResults is of type Dictionary<int, ItemBO>.

I get that item is of type KeyValuePair<int, ItemBO>, but would have thought that the cast from a list of that type to a Dictionary of that type would have been... er... "Natural".

Instead, to get the compiler to shut up, I needed to write this:

Dictionary<int, ItemBO> result = 
    ( from item in originalResults where item.Value.SomeCriteria == true
    select item.Value ).ToDictionary( GetItemKey );

Which, although not entirely counter-intuitive, suggests that a lot of unnecessary work unpackaging and repackaging the Dictionary is going on under the covers. Is there a better solution? Is there a concept I'm missing out on?

like image 415
Bob Kaufman Avatar asked Dec 31 '10 14:12

Bob Kaufman


1 Answers

Which, although not entirely counter-intuitive, suggests that a lot of unnecessary work unpackaging and repackaging the Dictionary is going on under the covers.

I'm not sure what you mean by "unnecessary" work. To perform this operation requires a lot of work - your query has to be fully evaluated, which involves scanning the entire dictionary and evaluating the predicate for each entry. Also, a new dictionary has to be created and populated to store the results. I think that it would be more of a problem if this work was hidden by an automatic conversion.

The real problem is that you're using your dictionary backwards. Lookups by key are fast, but lookups by value require scanning all items in the dictionary. If you could store the dictionary so that the value you are using to filter is the key then you will be able to make much faster lookups and with a cleaner syntax.

like image 99
Mark Byers Avatar answered Oct 04 '22 20:10

Mark Byers