C# Convert a list to a dictionary

By FoxLearn 1/21/2025 6:34:56 AM   25
The easiest way to convert a list into a dictionary is by using the LINQ ToDictionary() method.

For example, using LINQ

using System.Linq;

var employeeList = GetEmployeeList();
var employeesById = employeeList.ToDictionary(keySelector: e => e.Id, elementSelector: e => e);

This iterates through the list and applies the key and value selector lambdas you provide to construct the dictionary.

Using a Loop

If LINQ isn’t preferred, you can use a loop to achieve the same result:

var employees = GetEmployeeList();

var employeesById = new Dictionary<int, Employee>();

foreach (var employee in employees)
{
    employeesById.Add(employee.Id, employee);
}

This method typically has better performance compared to LINQ and might be preferred if performance is critical or LINQ is unfamiliar. Use whichever approach is more intuitive for your scenario.

Implicit Element Selector

These two statements produce the same result:

// Explicit element selector
var employeesById = employeeList.ToDictionary(keySelector: e => e.Id, elementSelector: e => e);

// Implicit element selector
var employeesById = employeeList.ToDictionary(keySelector: e => e.Id);

If you omit the elementSelector, the method defaults to using the list items as the values. This is often sufficient when indexing objects by one of their properties.

Handling Duplicate Keys

If the list contains duplicate keys, ToDictionary() throws an ArgumentException.

To address this, you can group the list by key and decide how to handle duplicates.

Aggregate a Value for Each Key

Suppose you want to count the number of employees per department:

var employees = new List<Employee> 
{
    new Employee { Id = 1, Department = "HR" },
    new Employee { Id = 2, Department = "IT" },
    new Employee { Id = 3, Department = "HR" }
};

var employeeCountByDept = employees
    .GroupBy(e => e.Department)
    .ToDictionary(keySelector: g => g.Key, elementSelector: g => g.Count());

foreach (var deptCount in employeeCountByDept)
{
    Console.WriteLine($"{deptCount.Key}={deptCount.Value}");
}

Output:

HR=2  
IT=1

Store a List of Elements for Each Key

This example groups employees by department and stores all employees in that department:

var employeesByDept = employees
    .GroupBy(e => e.Department)
    .ToDictionary(keySelector: g => g.Key, elementSelector: g => g.ToList());

foreach (var dept in employeesByDept)
{
    Console.WriteLine($"{dept.Key}={string.Join(", ", dept.Value.Select(e => e.Name))}");
}

Output:

HR=John, Jane  
IT=Alice

Select a First Element for Each Key

Sometimes, you only want the first employee per department:

var firstEmployeeByDept = employees
    .GroupBy(e => e.Department)
    .ToDictionary(keySelector: g => g.Key, elementSelector: g => g.First());

foreach (var dept in firstEmployeeByDept)
{
    Console.WriteLine($"{dept.Key}={dept.Value.Name}");
}

Handling Duplicates in a Loop

For a manual approach, check for existing keys before adding to the dictionary:

var employeesByDept = new Dictionary<string, List<Employee>>();

foreach (var employee in employees)
{
    if (!employeesByDept.ContainsKey(employee.Department))
    {
        employeesByDept[employee.Department] = new List<Employee>();
    }
    employeesByDept[employee.Department].Add(employee);
}

foreach (var dept in employeesByDept)
{
    Console.WriteLine($"{dept.Key}={string.Join(", ", dept.Value.Select(e => e.Name))}");
}

Output:

HR=John, Jane  
IT=Alice

This approach may feel more straightforward than using LINQ in some cases.