Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Transform a List To Dictionary of Lists

4.71/5 (6 votes)
15 Jun 2014CPOL2 min read 37.5K   95  
How to transform a list to a dictionary in 3 different ways?

Introduction

I often need to search for a specific item inside a list, but as you know, the complexity of List.Find is O(n). So, if you englobe your find in a foreach loop, you might risk a serious performance decrease with an O(n²) algorithm.

What I prefer to do is, transform my list to a dictionary because the dictionary[key] is only O(1) thanks to indexing. You can manually transform dictionary to a list through code but .NET Framework provides us with more sophisticated ways today. :)

The ToDictionary Way

C#
public Dictionary<string, string> TransformWithToDictionary()
{
    List<string> myList = new List<string>
    {
        "Brian",
        "Leslie",
        "Nathan",
        "Natalie",
        "Dimitry"
    };
    return myList.ToDictionary(k=>k);
}

Result will be a Dictionary<string, string> like this:

C#
Dictionary<string, string> result = new Dictionary<string,string>
    {
        {"Brian", "Brian"},
        {"Leslie", "Leslie"},
        {"Nathan", "Nathan"},
        {"Natalie","Natalie"},
        {"Dimitry", "Dimitry"}
    };

ToDictionary method converts List to Dictionary while giving you the hand to choose the dictionary key (thanks to the lambda expression).

You need to be careful from raising an exception when you insert an already existing key such as this example:

C#
return myList.ToDictionary(k=>k[0].ToString());

The expected result should be:

C#
Dictionary<string, string> myList = new Dictionary<string,string>
    {
        {"B", "Brian"},
        {"L", "Leslie"},
        {"N", "Nathan"},
        {"N","Natalie"},
        {"D", "Dimitry"}
    };

But this can't be realized due to the duplicated "N" key and will eventually result in an exception saying: an element with the same key already exists in the dictionary.

The Lookup Way

C#
public ILookup<string, string> TransformWithToLookup()
{
    List<string> myList = new List<string>
    {
        "Brian",
        "Leslie",
        "Nathan",
        "Nathan",
        "Dimitry"
    };
    return myList.ToLookup(k => k, v=>v[1].ToString());
}

The lookup mechanism is a bit different though:

  1. It groups values by keys inside a grouping
  2. It gives you the hand on what to retrieve from the value through a second lambda expression

The result can be accessed directly through keys:

C#
List<string> tempRes = result["Brian"].ToList(); 
//should return List<string> { "r" }

Or iterated through:

C#
foreach (var item in result)
{
    List<string> tempRes = item.ToList();
} 

Note that grouping can contain more than one value so if we do:

C#
var temp = res2["Nathan"].ToList();

The expected result would be:

C#
var temp = new List<string> { "a", "a" };

The Linq Way

C#
public Dictionary<string, List<string>> TransformWithLinq()
{
    List<string> myList = new List<string>
    {
        "Brian",
        "Leslie",
        "Nathan",
        "Nathan",
        "Dimitry"
    };
    return myList.GroupBy(k => k, v => v).ToDictionary(g =>g.Key, g=>g.ToList());
}

This way is a combination of Linq methods, let's analyse them one by one:

  1. The GroupBy groups values by keys
  2. The GroupBy returns an IEnumerable of Groupings containing key and its corresponding values
  3. Using the ToDictionary way, we get a dictionary of { key, list of values} without worrying about duplicated keys !

Voila:

C#
Dictionary<string, List<string>> result = new Dictionary<string, List<string>>
        {
            {"Brian", new List<string> {"Brian"}},
            {"Leslie", new List<string> {"Leslie"}},
            {"Nathan", new List<string> {"Nathan", "Nathan"}},
            {"Dimitry", new List<string> {"Dimitry"}},
        };

Credits

This tip aims to solve those tiny problems that we rarely care about. It may not be much for some people, but as a person looking to make my code as best as I can, it sure is a great way to save time and performance.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)