LINQ
C#
Dictionary
List
Programming

LINQ - Convert List to Dictionary with Value as List

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Introduction

When you want a dictionary whose values are lists, the usual LINQ pattern is to group the source items by key and then project each group into a list. In other words, this is usually a grouping problem, not a plain ToDictionary problem. Once that is clear, the code becomes straightforward and readable.

The Core Pattern: GroupBy Then ToDictionary

Suppose you have records with a key and a value.

csharp
1using System;
2using System.Collections.Generic;
3using System.Linq;
4
5public record Entry(string Key, int Value);
6
7var items = new List<Entry>
8{
9    new("A", 1),
10    new("A", 2),
11    new("B", 3),
12    new("B", 4),
13    new("C", 5)
14};
15
16var result = items
17    .GroupBy(x => x.Key)
18    .ToDictionary(g => g.Key, g => g.Select(x => x.Value).ToList());
19
20foreach (var pair in result)
21{
22    Console.WriteLine($"{pair.Key}: {string.Join(", ", pair.Value)}");
23}

That produces a dictionary where each unique key maps to a list of the associated values.

Why ToDictionary Alone Is Not Enough

A direct ToDictionary(x => x.Key, x => x.Value) only works when keys are unique. If the source contains repeated keys, it throws an exception.

csharp
var broken = items.ToDictionary(x => x.Key, x => x.Value);

That fails because A and B appear more than once. Grouping is the correct model when duplicate keys are expected.

Keeping Whole Objects Instead of Projected Values

Sometimes you do not want a Dictionary<TKey, List<TValue>>. You want a Dictionary<TKey, List<TItem>>.

csharp
var groupedObjects = items
    .GroupBy(x => x.Key)
    .ToDictionary(g => g.Key, g => g.ToList());

This is useful when later logic needs the full object rather than just one property.

A Small Reusable Helper

If you do this often, a helper method can keep the call sites clean.

csharp
1using System;
2using System.Collections.Generic;
3using System.Linq;
4
5public static class EnumerableExtensions
6{
7    public static Dictionary<TKey, List<TValue>> ToGroupedDictionary<TSource, TKey, TValue>(
8        this IEnumerable<TSource> source,
9        Func<TSource, TKey> keySelector,
10        Func<TSource, TValue> valueSelector)
11        where TKey : notnull
12    {
13        return source
14            .GroupBy(keySelector)
15            .ToDictionary(g => g.Key, g => g.Select(valueSelector).ToList());
16    }
17}

Then use it like this:

csharp
var dictionary = items.ToGroupedDictionary(x => x.Key, x => x.Value);

This keeps the intent obvious without repeating the grouping pipeline everywhere.

Preserve Ordering Carefully

The lists inside the dictionary preserve the order in which elements appear within each group based on the original sequence. If you need sorting, apply it before or after grouping.

For example, sort each value list descending:

csharp
1var sorted = items
2    .GroupBy(x => x.Key)
3    .ToDictionary(
4        g => g.Key,
5        g => g.Select(x => x.Value).OrderByDescending(v => v).ToList());

This is often useful when the grouped values will be displayed or processed in a specific priority order.

Use Lookup if Read-Only Grouping Is Enough

If you only need grouped access and do not specifically require a dictionary, ToLookup is another option.

csharp
var lookup = items.ToLookup(x => x.Key, x => x.Value);
Console.WriteLine(string.Join(", ", lookup["A"]));

A lookup is convenient for read-only grouped access, but it is not the same as a mutable dictionary of lists.

Common Pitfalls

  • Using ToDictionary directly when duplicate keys exist in the source.
  • Forgetting that grouping is the real operation when each key should map to multiple values.
  • Projecting the wrong thing inside the group and ending up with full objects when only values were needed, or vice versa.
  • Assuming ordering is automatic beyond the original sequence when later sorting rules actually matter.
  • Using a dictionary when a lookup would be simpler for read-only access.

Summary

  • If each key should map to multiple values, use GroupBy before ToDictionary.
  • A direct ToDictionary works only when keys are unique.
  • Project grouped items into ToList() to produce dictionary values as lists.
  • Keep full objects or projected values depending on what the rest of the code needs.
  • Use ToLookup when grouped read-only access is enough and mutability is unnecessary.

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.