views:

321

answers:

4

Hi, I declared the dictionary obj.

Dictionary<string, string> aDict = new Dictionary<string, string>(); 
        aDict .Add("IP", "Host"); 

As I remembered,

The expression of aDict[IP] can return the value (Host).

Now if I go in the opposite direction.

How to get the Key from Value ? aDict[Host] ?

Does the Dictionary is a one-way street in C#, only running from Key to Value ? thanks.

+3  A: 

Dictionary is a one way lookup. You can still loop over all entries in the Dictionary looking for the value "Host" if you need to. If you anticipate doing that a lot you might just want to use two dictionaries to and keep them both in sync.

Brian Ensink
+1  A: 

It is a one way street. Values are not supposed to be unique, so you cannot look up a key by value, except by enumerating the whole dictionary:

 foreach(string s in Dict.Keys)
 {
   if(Dict[s] == TheValue)
       ;//we found it!
 }
Seva Alekseyev
+1  A: 

Yes, the dictionary is basically a one way street. For example, it would be possible for many keys to have the value "Host", so there's no simple reverse lookup.

However, you can iterate over the dictionary noting which keys map to the desired value:

foreach (var entry in dict)
{
  if (entry.Value == desiredValue)
    found.Add(entry.Key);
}

Obviously this is not efficient for large dictionaries though.

itowlson
+12  A: 

Dictionaries do not work like this, nor are they intended to. How would you resolve the following:

key = "1", value = "x",
key = "2", value = "x"

You could do this:

var keys = dict.Where(kvp => kvp.Value == someValue).Select(kvp => kvp.Key);
foreach(var key in keys) {
    Console.WriteLine(key);
}

But if you really need to go back and forth between keys and values you should consider encapsulating the problem into a two-way map. Here's a very simple implementation of this that you can tailor to your needs:

class TwoWayDictionary<TLeft, TRight> {
    IDictionary<TLeft, TRight> leftToRight = new Dictionary<TLeft, TRight>();
    IDictionary<TRight, TLeft> rightToLeft = new Dictionary<TRight, TLeft>();

    public void Add(TLeft left, TRight right) {
        if (leftToRight.ContainsKey(left)) {
            throw new InvalidOperationException("key left is duplicate");
        }
        if (rightToLeft.ContainsKey(right)) {
            throw new InvalidOperationException("key right is duplicate");
        }
        leftToRight.Add(left, right);
        rightToLeft.Add(right, left);
    }

    public bool TryGetRightByLeft(TLeft left, out TRight right) {
        return leftToRight.TryGetValue(left, out right);
    }

    public bool TryGetLeftByRight(out TLeft left, TRight right) {
        return rightToLeft.TryGetValue(right, out left);
    }
}

Note that this assumes that no key is ever duplicated.

Now you can say:

TwoWayDictionary<string, string> dict = new TwoWayDictionary<string, string>();
dict.Add("127.0.0.1", "localhost");

string host;
dict.TryGetRightByLeft("127.0.0.1", out host);
// host is "localhost"

string ip;
dict.TryGetLeftByRight("localhost", out ip);
// ip is "127.0.0.1"
Jason
It's really Cool.
Nano HE