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

LINQ Extension Method to Return a Unique List Based on a Key

3.46/5 (5 votes)
5 Dec 2008CPOL 64.4K  
LINQ Extension method to return a Unique List based on a key

Introduction

This article is about a handy LINQ extension method that will take a List<T> and a key selector, and return a unique List<T> based on that key.

Background

I had a need to use an in-code way of refining a List<T> so there was no duplication on a key. I developed this handy LINQ Extension to do it for me.

Using the Code

Use this method on any List<T>. This is an extension method, so it has to be put in a static class.

Example

C#
List<MyClass> classList; 

Assuming classList is populated with values...

C#
List<MyClass> filteredList = classList.Unique(cl => cl.SomeKeyProperty);
C#
/// <summary>
/// Takes a List of type <typeparamref name="T"/> 
/// and a function as the key selector and returns a unique list of type 
/// <typeparamref name="T"/>
/// from that list
/// </summary>
/// <typeparam name="KEY">The type of the KEY.</typeparam>
/// <typeparam name="T"></typeparam>
/// <param name="InputList">The input list.</param>
/// <param name="func">The func.</param>
/// <returns></returns>
/// <example><code>List&lt;T&gt; uniqueList = 
/// 	nonUniqueList.Unique(key=>key.ID);</code></example>
public static List<T> Unique<KEY, T>(this List<T> InputList, Func<T, KEY> func)
{
    if (func == null)
        throw new ArgumentNullException("Key selector function cannot be null");

    if (InputList == null)
    { return null; }

    if (InputList.Count == 0)
    { return InputList; }

    // Convert the inputList to a dictionary based on the key selector provided
    Dictionary<KEY, T> uniqueDictionary = new Dictionary<KEY, T>();
    InputList.ForEach(item =>
    {
        // Use the key selector function to retrieve the key
        KEY k = func.Invoke(item);

        // Check the dictionary for that key
        if (!uniqueDictionary.ContainsKey(k))
        {
            // Add that item to the dictionary 
            uniqueDictionary.Add(k, item);
        }
    });

    // Get the enumerator of the dictionary
    Dictionary<KEY, T>.Enumerator e = uniqueDictionary.GetEnumerator();

    List<T> uniqueList = new List<T>();
    while (e.MoveNext())
    {
        // Enumerate through the dictionary keys and pull out 
        // the values into a unique list
        uniqueList.Add(e.Current.Value);
    }

    // return the unique list
    return uniqueList;
} 

Points of Interest  

While LINQ has a .ToDictionary() extension method, if you have a List<T> that contains items that aren't unique, .ToDictionary() will throw an exception indicating that a key already exists in the dictionary.  So I had to write the code above to only add items to the dictionary if they didn't already exist.

History

  • v1.0 12/05/2008

License

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