views:

56

answers:

4

Very often I use Dictionary<TKey, TValue> type to store ehh...dictionary type of values, e.g. Key = 1, Value ="Canada". But in many cases, values in the dictionary data is also unique, just like the Keys. And I find that for Dictionary<TKey, TValue> type, it is not very convenient to get key value based on value.

My question is, which class in .NET, is suitable in this scenario? Quickly find out Value based on Key and vice versa.

+2  A: 

Don't think there's anything that ships with .NET. There's probably a 3rd party class. But you could very easily build your own class, that contains two Dictionaries, one with the keys and values reversed.

SamStephens
A: 

You can mirror the Dictionary by using two dictionaries, but that will only work if the value collection is unique as well, which sounds odd and unlikely. Otherwise you would have to query the Values property for the correct one.

(
 from x in dict.Values
 where x.Prop == "someValue"
 select x
)
.FirstOrDefault()

OR, simply

dict.Values.FirstOrDefault(x => x.Prop == "someValue");
John Leidegren
+3  A: 

This is pretty trivial using LINQ:

int key = new Dictionary<int,string>().Where((kv)=>kv.Value == "SomeValue").Select(kv=>kv.Key).FirstOrDefault();

And an extension method if you fancy:

static class DictionaryExtensions {
    public static bool TryFindByValue<TKey, TValue>(this IDictionary<TKey, TValue> dict, TValue value, out TKey key) {
        var keys = dict.Where((kv) => kv.Value.Equals(value)).Select(kv => kv.Key);
        bool retValue = keys.Any();
        key = keys.FirstOrDefault();
        return retValue;
    }
}

What you can also do is to implement IDictionary, delegate to two Dictionary objects (one for key-value mapping and one for value-key mapping) for backing store and have a constraint on Add that values must be unique. That way you are guaranteed that there would be at most one entry with a particular value. EDIT Using two dictionaries will improve access time(Thanks @SamStephens) as both keys and values will be stored in an ordered hashtable.

Igor Zevaka
The same as `.FirstOrDefault(p=>p.Value=="SomeValue").Key;` but my is rather faster. (an additional null check is required in both cases)
abatishchev
Dereferencing Key in `.FirstOrDefault(p=>p.Value=="SomeValue").Key;` will crash if there are no key/value pairs satisfying the condition. It's safer to `FirstOrDefault()` right at the end of the fluent chain.
Igor Zevaka
Doesn't have the speed of accessing a Dictionary by Key
SamStephens
@SamStephens, Yes, that's true. I ll update the answer as well.
Igor Zevaka
+1  A: 

(requires .NET 4.0)

var list = new List<Tuple<int, string>>
{
 new Tuple<int, string>(1, "Canada"),
 new Tuple<int, string>(2, "USA")
};

var i = list.FirstOrDefault(t => t.Item1 == 1);
var j = list.FirstOrDefault(t => t.Item2 == "USA");
abatishchev
Wish I could give +2 for mention of tuples
johnc
Doesn't have the speed of accessing a Dictionary by Key
SamStephens