C# Linq Get Dictionary Where Value Not Equal

The idea here is to get the elements from a dictionary where the values do not match a given value. This is easily done with the Linq Where clause and a lambda expression:

var numbers = new Dictionary<int, string>()
{
	{ 1, "One" },
	{ 2, "Two" },
	{ 3, "Three" },
};

var results = numbers.Where(x => x.Value != "Two");

foreach (var result in results)
{
	Console.WriteLine(result);
}

This returns:

[1, One]
[3, Three]

I’ve used “Two” here as en example of the value you want to exclude, but you could easily use a variable or a passed in parameter.

Choosing what you return

Looking more closely at the variable I’ve called results, we can see it’s an IEnumerable (hover over the variable name in Visual Studio), so it could be written as:

IEnumerable<KeyValuePair<int, string>> results = numbers.Where(x => x.Value != "Two");

Assuming that’s not the type you’re after, we have a few options:

Get the list of Keys

var numbers = new Dictionary<int, string>()
{
    { 1, "One" },
    { 2, "Two" },
    { 3, "Three" },
};

var keys = numbers
    .Where(x => x.Value != "Two")
    .Select(x => x.Key);

foreach (var key in keys)
{
    Console.WriteLine(key);
}

Which returns:

1
3

Get the list of Values

var numbers = new Dictionary<int, string>()
{
    { 1, "One" },
    { 2, "Two" },
    { 3, "Three" },
};

var values = numbers
    .Where(x => x.Value != "Two")
    .Select(x => x.Value);

foreach (var value in values)
{
    Console.WriteLine(value);
}

Which outputs:

One
Three

Get a Dictionary

As always, there’s more than one way to achieve the required result:

Convert our IEnumerable into a Dictionary

var numbers = new Dictionary<int, string>()
{
    { 1, "One" },
    { 2, "Two" },
    { 3, "Three" },
};

var results = numbers
    .Where(x => x.Value != "Two")
    .ToDictionary(x => x.Key, x => x.Value);

foreach (var item in results)
{
    Console.WriteLine($"key: {item.Key}, value: {item.Value}");
}

This outputs:

key: 1, value: One
key: 3, value: Three

The only tricky bit here is that ToDictionary() takes two lambda expressions: one to select the key and another to select the value.

This would perform well if you’re removing most of the items from the dictionary, but I suspect it’s fairly slow if it’s a large dictionary and you’re only removing a few items from it.

If that’s the case, you probably want to:

Remove the offending items from the original dictionary

var numbers = new Dictionary<int, string>()
{
    { 1, "One" },
    { 2, "Two" },
    { 3, "Three" },
};

var ItemsToRemove = numbers
    .Where(x => x.Value == "Two")
    .ToList();

foreach (var item in ItemsToRemove)
{
    numbers.Remove(item.Key);
}

foreach (var number in numbers)
{
    Console.WriteLine($"key: {number.Key}, value: {number.Value}");
}

This is likely to be faster if your dictionary is large and you’re only removing a few values. It again outputs:

key: 1, value: One
key: 3, value: Three

I appreciate I’ve done some hand waving around the performance, sorry. Let me know in the comments below if you’d like to see some benchmarks comparing these last two options.

Leave a Reply

Your email address will not be published. Required fields are marked *