How to get a key from dictionary?

Jim Dennis jimd at vega.starshine.org
Tue Mar 26 03:20:12 EST 2002


In article <mailman.1017100600.5242.python-list at python.org>, Don Arnold wrote:


>> Hi,
>> Is there a possibility to get, from a dictionary, a key according to a
>> value ?
>> For example
>> I have a dictionary

>> dict={'aa':1,'bb':2}

>> and
>> dict['aa']
>> is 1

 You could create your own class which maintained *two* dictionaries.
 For every insertion into the main dictionary you'd insert an entry
 into the self.valuedex dictionary.  
 
 You could have an instance flag determine whether to allow non-unique 
 values.  If you allow non-unique values then each key in the 
 "valuedex" or "reverse_index" would be a list (of the keys where this 
 value is stored).  If you require unique values (as well as unique keys) 
 then you can raise a suitable exception when you detect a violation of 
 this policy (maybe you'd create a "ValueConstraintException" as a 
 subclass of KeyError or something like that).

 You might need another instance flag to handle any attempt to use
 lists (or other mutable objects) as values to assign into your 
 "doubly indexed" dictionary.  For simple flat lists it might be 
 reasonable to generate a tuple as the key for the reverse mapping 
 (valuedex).  Any you'll have to decide what sort of exception
 to raise for situations where you can't think of a suitable hashable
 representation of the value being added to the dictionary.

 It would even be possible to implement this with lazy evaluation of
 the reverse mapping.  Thus you'd leave the reverse mapping (valuedex)
 empty until an attempt to search it was made.  Then you'd generate it.
 Upon subsequent reverse searches you might check the dictionary first,
 return if found, and only re-generate/update the reverse mapping 
 when necessary.  (Intuitively I suspect that this would only make 
 sense when "unique value" constraints were in place; and possibly
 it would defer the checking for invalid (mutable/non-hashable) 
 values until it was unrecoverable; until it might be non-sensical
 to trap those exceptions).

 Anyway, those are your choices:  If you want fast and efficient
 access to the "keys" from the "values" then you need to index those
 as well (most readily done by maintaining a reverse mapping 
 dictionary).  This entails some of the same constraints on your 
 values that you should already expect from your keys (uniqueness and
 hashability/immutability).  If you don't need the reverse access to
 be as fast or efficient then you can simply iterate over the items
 list; either breaking on the first match (if you expect your values
 to be unique, or if you only want a single match) or looping through
 the whole list of items and building a list of return values.
 
 A simple list comprehension method for getting all of the keys
 for a give value is:

 	
		matches = [ x for x,y in d.items() if y ... ]

 ... where d is the dictionary, and ... is replaced with some 
 comparison or conditional.

 I could wrap that pattern in a function:

 	def searchvalues(d,f)
		return [ x for x,y in d.items() if f(y) ]

 ... though the invocation might be a bit non-intuitive since
 it would require that the user construct some sort of function,
 possibly a lambda function which would only take one argument
 and return a boolean on it.  This hides the condition being tested
 in a remote bit of code.

 If I had a real need for this I might come up with a way to pass
 additional arguments to searchvalues (kind of like the os.path.walk()
 function).  In practice my comparison function might be a closure,
 though the scoping for that might become a bit of a nightmare.





More information about the Python-list mailing list