How to check if a key/value pair exists in a Dictionary?
Asked Answered
L

11

31

How can one check if a key/value pair exists in a Dictionary<TKey,TValue>? I'm able to check if a key or value exist, using ContainsKey and ContainsValue, but I'm unsure of how to check if a key/value pair exist.

Lsd answered 10/3, 2012 at 21:33 Comment(0)
L
47

Well the pair can't exist if the key doesn't exist... so fetch the value associated with the key, and check whether that's the value you were looking for. So for example:

// Could be generic of course, but let's keep things simple...
public bool ContainsKeyValue(Dictionary<string, int> dictionary,
                             string expectedKey, int expectedValue)
{
    int actualValue;
    if (!dictionary.TryGetValue(expectedKey, out actualValue))
    {
        return false;
    }
    return actualValue == expectedValue;
}

Or slightly more "cleverly" (usually something to avoid...):

public bool ContainsKeyValue(Dictionary<string, int> dictionary,
                             string expectedKey, int expectedValue)
{
    int actualValue;
    return dictionary.TryGetValue(expectedKey, out actualValue) &&
           actualValue == expectedValue;
}
Larkspur answered 10/3, 2012 at 21:35 Comment(0)
E
30

A dictionary only supports one value per key, so:

// key = the key you are looking for
// value = the value you are looking for
YourValueType found;
if(dictionary.TryGetValue(key, out found) && found == value) {
    // key/value pair exists
}
Eleazar answered 10/3, 2012 at 21:36 Comment(2)
I slightly dislike setting and using found in one expression.Tanker
I know it's well defined. It's just a stylistic preference. Just like I try to have only a single side-effect per statement which is also the last thing happening in that statement.Tanker
C
8
if (myDic.ContainsKey(testKey) && myDic[testKey].Equals(testValue))
     return true;
Comatose answered 10/3, 2012 at 21:36 Comment(2)
Yes, it works. It's not as illustrative. I chose this one to make the logic clear, not to optimize performance.Comatose
This particular scenario we are talking about, is not about (micro) optimization. It's more about understanding how .NET dictionaries work, O(k) complexities etc. Its the right practice to use trygetvalue here.Mesopause
C
4

You can do this by using dictionary.TryGetValue.

Dictionary<string, bool> clients = new Dictionary<string, bool>();
                    clients.Add("abc", true);
                    clients.Add("abc2", true);
                    clients.Add("abc3", false);
                    clients.Add("abc4", true);

                    bool isValid = false;

                    if (clients.TryGetValue("abc3", out isValid)==false||isValid == false)
                    {
                        Console.WriteLine(isValid);
                    }
                    else
                    {
                        Console.WriteLine(isValid);
                    }

At the above code if condition there is two sections first one for checking key has value and second one for comparing the actual value with your expected value.

First Section{clients.TryGetValue("abc3", out isValid)==false}||Second Section{isValid == false}
Crabbing answered 3/11, 2015 at 5:6 Comment(0)
S
2

Simple, Generic Extension Method

Here's a quick generic extension method that adds a ContainsPair() method to any IDictionary:

public static bool ContainsPair<TKey, TValue>(this IDictionary<TKey, TValue> dictionary,
                                                   TKey key,
                                                   TValue value)
{
    return dictionary.TryGetValue(key, out var found) && found.Equals(value);
}

This allows you to do checks against dictionaries like this:

if( myDict.ContainsPair("car", "mustang") ) { ... }     // NOTE: this is not case-insensitive

Case-Insensitive Check

When working with string-based keys, you can make the Dictionary case-insensitive with regard to its keys by creating it with a comparer such as StringComparer.OrdinalIgnoreCase when the dictionary is constructed.

However, to make the value comparison case insensitive (assuming the values are also strings), you can use this version that adds an IComparer parameter:

public static bool ContainsPair<TKey, TValue>(this IDictionary<TKey, TValue> dictionary,
                                                   TKey key,
                                                   TValue value,
                                                   IComparer<TValue> comparer)
{
    return dictionary.TryGetValue(key, out var found) && comparer.Compare(found, value) == 0;
}
Skew answered 3/8, 2018 at 14:13 Comment(0)
R
1

Generic version of Jon Skeet's answer

        public bool ContainsKeyValue<TKey, TVal>(Dictionary<TKey, TVal> dictionnaire,
                                             TKey expectedKey,
                                             TVal expectedValue) where TVal : IComparable
    {
        TVal actualValue;

        if (!dictionnaire.TryGetValue(expectedKey, out actualValue))
        {
            return false;
        }
        return actualValue.CompareTo(expectedValue) == 0;
    }
Reavis answered 16/11, 2017 at 15:46 Comment(0)
A
0

How something like this

bool exists = dict.ContainsKey("key") ? dict["key"] == "value" : false;
Avid answered 10/3, 2012 at 21:36 Comment(0)
A
0
var result= YourDictionaryName.TryGetValue(key, out string value) ? YourDictionaryName[key] : "";

If the key is present in the dictionary, it returns the value of the key otherwise it returns a blank object.

Hope, this code helps you.

Armyworm answered 29/5, 2019 at 12:22 Comment(0)
D
0

This functionality is already available out of the box, but it's hidden in the Contains method of the ICollection<KeyValuePair<TKey, TValue>> interface, which the Dictionary<TKey,TValue> class implements. Here is how it can be exposed as a public extension method:

public static bool Contains<TKey, TValue>(this Dictionary<TKey, TValue> dictionary,
    TKey key, TValue value)
{
    ArgumentNullException.ThrowIfNull(dictionary);
    return ((ICollection<KeyValuePair<TKey, TValue>>)dictionary).Contains(new(key, value));
}

Online demo.

Dipteral answered 16/12, 2022 at 13:27 Comment(0)
E
-1

First you check if the key exists, if so, you get the value for this key and compare it to the value you are testing... If they are equal, your Dictionary contains the pair

Emptor answered 10/3, 2012 at 21:36 Comment(0)
G
-1

Please check with following code

var dColList = new Dictionary<string, int>();
if (!dColList.Contains(new KeyValuePair<string, int>(col.Id,col.RowId)))
{}

Thanks, Mahesh G

Granddaddy answered 14/3, 2017 at 15:18 Comment(8)
This is going to be a lot slower than the other options as you're not leveraging the dictionaries ability to do fast lookups on its key.Johathan
@Johathan The lookup is very fast in this case. The actual implemementation in Dictionary.cs first does lookup for dictionary entry by Key and then compares the Value. This answer provides quite an elegant and fast solution.Balough
@Balough Dictionary<TKey,TValue> does not have a Contains method. This is using the LINQ extension of IEnumerable<T> that does a linear search of the sequence, and is not able to use the dictionary's ability to look up a key based on it's hash. There are numerous other answers here that do this correctly using actual methods of the dictionary that leverage it's fast searching.Johathan
@Johathan That's not true. Please check the source file referencesource.microsoft.com/#mscorlib/system/collections/… The Contains() method. It starts with the int i = FindEntry(keyValuePair.Key);. It first does lookup for key and then compares the value if(i >= 0 && EqualityComparer<TValue>.Default.Equals(entries[i].value, keyValuePair.Value)). It doesn't use linear search.Balough
@Balough But that's not the method that's being called. That's the explicit interface implementation for ICollection.Contains. This is calling the LINQ Contains method.Johathan
@Johathan Why do you think it is not being called? Why would somebody write that method inside the Dictionary class if it would not be called?Balough
@Balough Why do you think it is being called? I'm not saying the method isn't callable, I'm just saying this code isn't calling it, it's calling a different method, with a different implementation. The explicit interface implementation will only be called when the compile time type of the expression is that interface, which isn't the case here.Johathan
@Johathan the Dictionary class implements interface IDictionary<TKey, TValue> which extends ICollection<KeyValuePair<TKey, TValue>> and the method signature is bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> keyValuePair). Therefore the Dictionary class implements the interface method and it will be called.Balough

© 2022 - 2024 — McMap. All rights reserved.