[Tutor] How to get Key from multiple value dictionary search

Martin A. Brown martin at linux-ip.net
Wed Jan 6 18:48:00 EST 2016


Hello there,

>I refer to this website
>https://www.codecademy.com/forum_questions/50721fce7c7091000201e56a
>
>dic = {'key1': ["value1",  "value2"],
>       'key2': ["value77", "something"] }
>
>what I wanted to learn is :
>
>a) how do i get the key only by providing value i.e value77 ?

N.B.  First, see below for more discussion about complexity of the 
data you have in this sample dictionary. (As a result,) Second, I 
have revised your question to

How do I get the keys [pl.] by providing only the value, i.e. 'value77'?

  >>> [k for k, v in dic.iteritems() if 'value77' in v]
  ['key2']

The above is very similar to the example in the codecademy.com link, 
but it returns the key instead of simply showing a True or False.

>b) Please help to break the code(instead of one liner) so that i 
>can understand properly

Yes, of course.  That list comprehension syntax is dense.  There are 
many descriptions of list comprehension and even the link you 
provided includes a reference to the Python documentation.  Here it 
is (again) for anybod else following along:

  https://docs.python.org/2/tutorial/datastructures.html#list-comprehensions

If you do not understand list comprehensions yet, it is always a 
good exercise to see if you can write the same thing with a loop.  
Here's my loop to do the same thing.  Note that I am creating a list 
variable with no entries before the loop.

    l = list()
    for k, v in dic.iteritems():
        if 'value77' in v:
            l.append(k)
    return l

I like writing little functions (the function name here is not very 
creative, though). Anyway, here's a little function that you can 
call that will return the list of all keys whose values contain the 
item of interest:

  def get_all_keys_if_value(d, sought):
      l = list()
      for k, v in d.iteritems():
          if sought in v:
              l.append(k)
      return l

You can call this function like:

  keys_of_interest = get_all_keys_if_value(dic, 'value77')

(Detour begins)

If you are confused about dic.iteritems(), then go to a Python 
console and observe the different results for these:

   >>> dic.keys()
  ['key2', 'key1']
  >>> dic.values()
  [['value77', 'something'], ['value1', 'value2']]
  >>> list(dic.iteritems())
  [('key2', ['value77', 'something']), ('key1', ['value1', 'value2'])]

(Return from detour)

Now, I would like to address the complexity of your data structure.  
There is the following guarantee for a dictionary:  There can be 
only one single entry for each unique key.  In short, the keys are 
always unique.

Your question (in this case) is about searching through the values.  
There's no easy way to lookup based on the values, only keys.

You might be tempted to build a new dictionary (invert yours) and 
use each of the strings, extracted from the lists (dictionary 
values) as the keys in the new dictionary.  It would work for you in 
this case.  The result would be:

  invdic = {'something': 'key2',
   'value1': 'key1',
   'value2': 'key1',
   'value77': 'key2'}

Then you could find the key for 'value77' very simply:

  invdic['value77']  # -- this would be 'key2'

As I mentioned, this would work just fine in your data example, but 
here be dragons!

Your data structure represents a many-to-many data set.  Each 
dictionary value contains a Python list of strings.

It is possible that every single key could point to a list that 
contains the string 'value77'.
  
For example, what happens when somebody adds a new key 'key3' to 
your dictionary and then the dictionary looks like this:

  newdic = {'key1': ['value1', 'value2'],
         'key2': ['value77', 'something'],
         'key3': ['value77'],
         'key4': ['value77', 'value1']}

What would you expect to be returned here:

  keys_of_interest = get_all_keys_if_value(newdic, 'value77')

Well, they should be:

  ['key3', 'key2', 'key4']  # -- keys_of_interest

I may have gone a bit far afield from your original question, but I 
hope you see why I identified the point about the dictionary value 
as a list.  This means the answer could contain anywhere from zero 
keys (the value is not present in any list in the dictionary values) 
OR all keys (the value is present in every list in the dictionary 
values).  {Whew.}

Good luck and have fun,

-Martin

-- 
Martin A. Brown
http://linux-ip.net/


More information about the Tutor mailing list