PowerCollections.MultiDictionary

¿Quieres leer esto en español? Ven acá.

My friend Harley came by with an interesting problem: he had a list of Person objects with properties like id, first name, last name, etc. Now Harley needed to search for people in the list by lastname, what comes immediately to your mind is to use a people dictionary Dictionary<string, Person> and then to search the dictionary with something like peopleByLastName["Smith"], the problem is that .NET Dictionary doesn't accept duplicate keys and of course there are a lot of Smiths ¿what to do? Harley wanted to use a DataSet, populate a DataTable with the list, and then use the DataTable's filtering facilities. It works, but it's a little like killing a bird with a missile. It so happens that the nice guys at Wintellect offer PowerCollections a family of collections that complement those available in .NET, therein they offer MultiDictionary which is a dictionary that accepts duplicate keys, just what Harley was needing. To create a multiDictionary keyed by lastname with the objects of a list you can do something like this:

private MultiDictionary<string, Person> GetPeopleByLastName(IEnumerable<Person> people)

{

  MultiDictionary<string, Person> peopleByLastName = new MultiDictionary<string, Person>(true);

  foreach (Person person in people)

  {

    peopleByLastName.Add(person.LastName, person);

  }

  return peopleByLastName;

}

The true argument in the constructor is the one that allows us to have duplicate keys so that we can enter several people with the same lastname in the dictionary. Now to fetch all the people with a given lastname it's enough to write:

  ICollection<Person> peopleWithGivenLastName = myPeopleByLastName[lastName];

Note that the lastName index returns a collection which can have zero, one or many objects ¡and that's it! Now Harley can search by lastname with duplicates and multiple results. Even better, PowerCollections is free (beer and speech wise), although you do have to register at the site before being able to download it.

Published Wednesday, May 31, 2006 5:53 PM by Edgar Sánchez

Comments

# re: PowerCollections.MultiDictionary

Thursday, June 01, 2006 9:50 AM by mike
Why not use List<Person> and then use anonymous delegates to search? The dictionary search will probably be faster...but you can only do a lookup by lastname.

       List<Person> people = new List<Person>();

       someotherlist = people.FindAll(delegate(Person person)
       {
           if (person.LastName.ToLower() == "smith")
           {
               return true;
           }
           else
           {
               return false;
           }
       });

# re: PowerCollections.MultiDictionary

Thursday, June 01, 2006 1:22 PM by Brandon Furtwangler
MultiDictionary is nice, but another option would be a dictionary of lists.

ie
Dictionary<string, List<Person>>

# re: PowerCollections.MultiDictionary

Thursday, June 01, 2006 2:48 PM by Jonathan Allen
Um, because its dog slow and total overkill?

That pattern makes sense when doing something complex inside the delegate. However, in this case alll is does is kill performance. Aside from losing the advantages of an indexed search, you have to make N function calls just to account for the delegate. And you still have to handle the processing inside the loop.

Now write the following 100 times...

I will not write "If (X) {return true;}else {return false;}" ever again. Instead I will just write "return (X);" like a normal person.


Leave a Comment

(required) 
(required) 
(optional)
(required)