6

I have this dictionary in python

d={1: 'a', 2: 'b', 3: 'c'}

with d[1] I get

>>> d[1]
'a'

how I can get the key correspond to a value ?
example : with 'a' get 1

JuanPablo
  • 23,792
  • 39
  • 118
  • 164
  • 3
    You want to invert the mapping. This question answers that: http://stackoverflow.com/questions/483666/python-reverse-inverse-a-mapping – Jonathon Reinhart Dec 27 '11 at 23:43
  • 1
    @JonathonReinhart I'm not sure that he wants to invert the mapping. I think that the question is about getting *1 key* from a value, and there're probably some way to do it faster – FunkySayu Jun 22 '15 at 07:50
  • @JonathonReinhart okay in fact i'm not sure : in the title we have "keys" and in the question we have "the key"... – FunkySayu Jun 22 '15 at 11:53

5 Answers5

8

You want to invert the mapping:

As shown in this question

dict((v,k) for k, v in map.iteritems())
Community
  • 1
  • 1
Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328
  • 2
    Doesn't this nuke some of his data in the new dict if he has multiple items with the same value? – Interrobang Dec 28 '11 at 00:06
  • 2
    @Interrobang that is unavoidable; if there are multiple items with the same value, then it is simply ambiguous which key to return for a given value anyway. – Karl Knechtel Dec 28 '11 at 00:20
  • This might work with the example given but: I don't think it's what was being asked, and it doesn't cover all cases. – gdvalderrama Mar 03 '17 at 09:52
  • The only way to work around the issue brought up by @Interrobang would be to invert the mapping, but make the values of the new dict be a list of all matching keys from the old dict. – Jonathon Reinhart Mar 10 '17 at 16:38
4

In the case you are looking for getting only one value, there's probably a faster way to do that. If you are sure that the value exists in your dictionnary, then :

my_value = 'a'
return next(key for key, value in d.iteritems() if value == my_value)

If you are not sure about getting a result, you can surround that by a try/except catching the StopIteration exception.

Here, dictionnary's items are generated until the value match. If you have a very large dictionnary, this trick may be faster in some cases.


Using a large set of data :

d1={1: 1, 2: 2, 3: 8, 4: 3, 5: 6, 6: 9, 7: 17, 8: 4, 9: 20, 10: 7, 11: 15,
    12: 10, 13: 10, 14: 18, 15: 18, 16: 5, 17: 13, 18: 21, 19: 21, 20: 8,
    21: 8, 22: 16, 23: 16, 24: 11, 25: 24, 26: 11, 27: 112, 28: 19, 29: 19,
    30: 19, 3077: 36, 32: 6, 33: 27, 34: 14, 35: 14, 36: 22, 4102: 39, 38: 22,
    39: 35, 40: 9, 41: 110, 42: 9, 43: 30, 44: 17, 45: 17, 46: 17, 47: 105, 48: 12,
    49: 25, 50: 25, 51: 25, 52: 12, 53: 12, 54: 113, 1079: 50, 56: 20, 57: 33,
    58: 20, 59: 33, 60: 20, 61: 20, 62: 108, 63: 108, 64: 7, 65: 28, 66: 28, 67: 28,
    68: 15, 69: 15, 70: 15, 71: 103, 72: 23, 73: 116, 74: 23, 75: 15, 76: 23, 77: 23, 
    78: 36, 79: 36, 80: 10, 81: 23, 82: 111, 83: 111, 84: 10, 85: 10, 86: 31, 87: 31, 
    88: 18, 89: 31, 90: 18, 91: 93, 92: 18, 93: 18, 94: 106, 95: 106, 96: 13, 9232: 35, 
    98: 26, 99: 26, 100: 26, 101: 26, 103: 88, 104: 13, 106: 13, 107: 101, 1132: 63, 
    2158: 51, 112: 21, 113: 13, 116: 21, 118: 34, 119: 34, 7288: 45, 121: 96, 122: 21, 
    124: 109, 125: 109, 128: 8, 1154: 32, 131: 29, 134: 29, 136: 16, 137: 91, 140: 16, 
    142: 104, 143: 104, 146: 117, 148: 24, 149: 24, 152: 24, 154: 24, 155: 86, 160: 11, 
    161: 99, 1186: 76, 3238: 49, 167: 68, 170: 11, 172: 32, 175: 81, 178: 32, 179: 32, 
    182: 94, 184: 19, 31: 107, 188: 107, 190: 107, 196: 27, 197: 27, 202: 27, 206: 89, 
    208: 14, 214: 102, 215: 102, 220: 115, 37: 22, 224: 22, 226: 14, 232: 22, 233: 84, 
    238: 35, 242: 97, 244: 22, 250: 110, 251: 66, 1276: 58, 256: 9, 2308: 33, 262: 30, 
    263: 79, 268: 30, 269: 30, 274: 92, 1300: 27, 280: 17, 283: 61, 286: 105, 292: 118, 
    296: 25, 298: 25, 304: 25, 310: 87, 1336: 71, 319: 56, 322: 100, 323: 100, 325: 25, 
    55: 113, 334: 69, 340: 12, 1367: 40, 350: 82, 358: 33, 364: 95, 376: 108, 
    377: 64, 2429: 46, 394: 28, 395: 77, 404: 28, 412: 90, 1438: 53, 425: 59, 430: 103, 
    1456: 97, 433: 28, 445: 72, 448: 23, 466: 85, 479: 54, 484: 98, 485: 98, 488: 23, 
    6154: 37, 502: 67, 4616: 34, 526: 80, 538: 31, 566: 62, 3644: 44, 577: 31, 97: 119, 
    592: 26, 593: 75, 1619: 48, 638: 57, 646: 101, 650: 26, 110: 114, 668: 70, 2734: 41, 
    700: 83, 1732: 30, 719: 52, 728: 96, 754: 65, 1780: 74, 4858: 47, 130: 29, 790: 78, 
    1822: 43, 2051: 38, 808: 29, 850: 60, 866: 29, 890: 73, 911: 42, 958: 55, 970: 99, 
    976: 24, 166: 112}

I compared the following functions in order to check which one was the fastest.

def f1():  
    return next(key for key, value in d1.iteritems() if value == 55)

def f2a():
    return [item[0] for item in d1.items() if item[1] == 55][0]

def f2b():
    return [item[0] for item in d1.iteritems() if item[1] == 55][0]

def f3():
    return dict((v, k) for k, v in d1.iteritems())[55]

tl=["f1", "f2a", "f2b", "f3"]
from timeit import Timer
cmpthese(1000, tl)

And here are the results :

f3   21182/s  --   -39%   -40%   -56%
f2a  34450/s    63%  --    -3%   -29%
f2b  35368/s    67%     3%  --   -27%
f1   48367/s   128%    40%    37%  --

f1 is faster that any other one.

FunkySayu
  • 7,641
  • 10
  • 38
  • 61
4

You could create a new dictionary from the keys and values in the initial one:

>>> d2 = dict((v, k) for k, v in d.iteritems())
>>> d2
{'a': 1, 'c': 3, 'b': 2}
>>> d2['a']
1
srgerg
  • 18,719
  • 4
  • 57
  • 39
3
key = 'a'
return [item[0] for item in self.items() if item[1] == key]

This will find all keys with value 'a' and return a list of them.

Interrobang
  • 16,984
  • 3
  • 55
  • 63
  • Note that this isn't nearly as (asymptomically) efficent as lookup by key. If you need to do this several times on dicts of considerable size, the other approach may be far more efficent. –  Dec 27 '11 at 23:59
2
Key = next((x for x in d if d[x] == 'a'), None)

This gives the desired result if only one corresponding key exists. (In O(n) time?) Since it quits immediately once it finds a qualified key.

Keys = [x for x in d if d[x] == 'a']

gives all qualified keys (in a list). And it returns an empty list if there are no such keys. This method is called 'list comprehension'.

Avoid getting keys by values whenever possible. It's quite inefficient comparing to accessing values from keys in O(1).

This implies that you wanna create a inversely mapping dict where keys and values of old dict are switched as values and keys in the new dict -- if you are gonna use this method frequently thereafter.

wangsrii
  • 21
  • 2