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






3.46/5 (5 votes)
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
List<MyClass> classList;
Assuming classList
is populated with values...
List<MyClass> filteredList = classList.Unique(cl => cl.SomeKeyProperty);
/// <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<T> 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