459,528 Members | 1,375 Online
Need help? Post your question and get tips & solutions from a community of 459,528 IT Pros & Developers. It's quick & easy.

# [dictionary] how to get key by item

 P: n/a saluton al ciuj i know how to get item by key ================== dict = {10 : 50, 2 : 12, 4 : 43} print dict[2] 12 but i wonder how to get key by item print dict[12] 2 ================== is there a more fast way than that one (my dictionary is really big) ================== dict = {10 : 50, 2 : 12, 4 : 43} item = 12 for key in dict.keys(): if dict[key] == item: print key break ================== Jul 18 '05 #1
11 Replies

 P: n/a Egor> i know how to get item by key ... Egor> but i wonder how to get key by item Assuming your dictionary defines a one-to-one mapping, just invert it: forward = {10 : 50, 2 : 12, 4 : 43} reverse = dict([(v,k) for (k,v) in forward.iteritems()]) print forward {10: 50, 4: 43, 2: 12} print reverse {50: 10, 43: 4, 12: 2} That doubles your storage, so you'll have to trade that off against the speed gain of not having to loop over the entire dictionary. Skip Jul 18 '05 #2

 P: n/a In article , Skip Montanaro wrote: Egor> i know how to get item by key ... Egor> but i wonder how to get key by item Assuming your dictionary defines a one-to-one mapping, just invert it: >>> forward = {10 : 50, 2 : 12, 4 : 43} >>> reverse = dict([(v,k) for (k,v) in forward.iteritems()]) >>> print forward {10: 50, 4: 43, 2: 12} >>> print reverse {50: 10, 43: 4, 12: 2} That doubles your storage, so you'll have to trade that off against the speed gain of not having to loop over the entire dictionary. Well, you *do* loop over the entire dictionary, but you only do it once, when you create the reverse dict. If you are only going to do a single lookup, it's no gain, but if you amortize the cost over many lookups, it's almost certainly a big win. This raises an interesting question. Let's assume that you add all the entries to the dictionary before you do any lookups, and you then need to lookup things up in both directions. Which is faster, to simultaneously build both the forward and reverse dicts, or to just build the forward one and when you're done doing that, build the reverse one in a single shot with the above list comprehension? BTW, does Python really build the intermediate list and throw it away after using it to initialize the dictionary, or is it smart enough to know that it doesn't really need to build the whole list in memory? Jul 18 '05 #3

 P: n/a That doubles your storage, so you'll have to trade that off against the speed gain of not having to loop over the entire dictionary. Roy> Well, you *do* loop over the entire dictionary, but you only do it Roy> once, when you create the reverse dict. If you are only going to Roy> do a single lookup, it's no gain, but if you amortize the cost over Roy> many lookups, it's almost certainly a big win. Sure, but the OP said his dictionary was big. It's up to him to decide whether the space-time tradeoff is worth it (or even possible). Roy> BTW, does Python really build the intermediate list and throw it Roy> away after using it to initialize the dictionary, or is it smart Roy> enough to know that it doesn't really need to build the whole list Roy> in memory? That's why I called .iteritems() in my example. It won't generate the entire list of tuples as .items() would. Skip Jul 18 '05 #4

 P: n/a Skip Montanaro wrote: Roy> BTW, does Python really build the intermediate list and throw it Roy> away after using it to initialize the dictionary, or is it smart Roy> enough to know that it doesn't really need to build the whole list Roy> in memory? That's why I called .iteritems() in my example. It won't generate the entire list of tuples as .items() would. I know it won't generate the list of items from the forward dict, but I was thinking of the list generated by the list comprehension, passed as the argument to the reverse dict constructor. That's the throw-away list I was thinking of (see Tim Delaney's response to my post). Jul 18 '05 #5

 P: n/a In article , Skip Montanaro wrote:Assuming your dictionary defines a one-to-one mapping, just invert it: >>> forward = {10 : 50, 2 : 12, 4 : 43} >>> reverse = dict([(v,k) for (k,v) in forward.iteritems()]) >>> print forward {10: 50, 4: 43, 2: 12} >>> print reverse {50: 10, 43: 4, 12: 2}That doubles your storage, so you'll have to trade that off against thespeed gain of not having to loop over the entire dictionary. To be precise, it doubles the storage of the *dictionary*, but it does *NOT* double the storage of the keys and items. Depending on how big those are, the cost of building a second dict might be mostly lost in the noise. -- Aahz (aa**@pythoncraft.com) <*> http://www.pythoncraft.com/ "19. A language that doesn't affect the way you think about programming, is not worth knowing." --Alan Perlis Jul 18 '05 #6

 P: n/a Skip Montanaro wrote: Egor> i know how to get item by key ... Egor> but i wonder how to get key by item Assuming your dictionary defines a one-to-one mapping, just invert it: >>> forward = {10 : 50, 2 : 12, 4 : 43} >>> reverse = dict([(v,k) for (k,v) in forward.iteritems()]) >>> print forward {10: 50, 4: 43, 2: 12} >>> print reverse {50: 10, 43: 4, 12: 2} That doubles your storage, so you'll have to trade that off against the speed gain of not having to loop over the entire dictionary. Skip But beware that all the items in the original dictionary must be hashable. The example shows just integers, so I assume they are in this case. But generally, this may not work. -- \/ \/ (O O) -- --------------------oOOo~(_)~oOOo---------------------------------------- Keith Dart vcard: public key: ID: F3D288E4 URL: ================================================== ========================== Jul 18 '05 #7

 P: n/a Skip Montanaro wrote: That doubles your storage careful: it creates another dictionary structure with the same size as the first one, but it doesn't copy the objects in the dictionary. so whether it doubles the actual memory usage depends on what data you have in the dictionary (last time I checked, ints and dictionary slots were the same size, but I cannot think of any other object that isn't larger...) (but you knew that, of course) Jul 18 '05 #8

 P: n/a Skip Montanaro wrote: Egor> i know how to get item by key ... Egor> but i wonder how to get key by item Assuming your dictionary defines a one-to-one mapping, just invert it: >>> forward = {10 : 50, 2 : 12, 4 : 43} >>> reverse = dict([(v,k) for (k,v) in forward.iteritems()]) >>> print forward {10: 50, 4: 43, 2: 12} >>> print reverse {50: 10, 43: 4, 12: 2} That doubles your storage, so you'll have to trade that off against the speed gain of not having to loop over the entire dictionary. Skip If some keys has the same value as the item this will cause problems because keys in your result dictionary can be overwritten. Could it be a option to build the result dictionary as a dictionary with the values as the keys, and lists of keys as the value. Perhaps you need to use a loop for this. -- -------------------------------------- Ola Natvig infoSense AS / development Jul 18 '05 #9

 P: n/a Ola Natvig wrote: If some keys has the same value as the item this will cause problems because keys in your result dictionary can be overwritten. Could it be a option to build the result dictionary as a dictionary with the values as the keys, and lists of keys as the value. Perhaps you need to use a loop for this. <> ..>>> d = dict(foo=1, bar=1, bob=7, jane=42, mary=16, fred=16) ..>>> from itertools import groupby ..>>> val = d.__getitem__ ..>>> grouped = groupby(sorted(d.iterkeys(), key=val), val) ..>>> r = dict((value, list(keys)) for value, keys in grouped) ..>>> r {16: ['mary', 'fred'], 1: ['bar', 'foo'], 42: ['jane'], 7: ['bob']} Cheers, Nick. -- Nick Coghlan | nc******@email.com | Brisbane, Australia --------------------------------------------------------------- http://boredomandlaziness.skystorm.net Jul 18 '05 #10

 P: n/a Fredrik> Skip Montanaro wrote: That doubles your storage Fredrik> careful: it creates another dictionary structure with the same Fredrik> size as the first one, but it doesn't copy the objects in the Fredrik> dictionary. Yes, sorry. The OP indicated the original dictionary was very big, so it seemed like duplicating the dictionary storage would potentially be costly since dictionaries hold extra storage (on average, twice the storage needed to hold the references to its keys?) to support O(1) average time lookup. Skip Jul 18 '05 #11

 P: n/a Ola> If some keys has the same value as the item this will cause Ola> problems because keys in your result dictionary can be Ola> overwritten. That's why I said, "assuming your dictionary defines a one-to-one mapping...". Skip Jul 18 '05 #12

### This discussion thread is closed

Replies have been disabled for this discussion.