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