0

I have a little code but I don't know how to find the key in a dictionary by using the value. Here I have my code and what I want to do:

NAMES = ['Alice', 'Bob', 'Cathy', 'Dan', 'Ed', 'Frank',
         'Gary', 'Helen', 'Irene', 'Jack', 'Kelly', 'Larry']

AGES = [20, 21, 18, 18, 19, 20, 20, 19, 19, 19, 22, 19]


def combine(list1,list2):
    dictionary = dict(zip(list1,list2))
    return dictionary

def people(age):
    if leeftijd in dictionary:
        return ['Bob']


print combine(NAMES, AGES)

print people(21) == ['Bob'] 
print people(22) == ['Kelly']
print people(23) == []

In this code I first put the list NAMES and AGES into a dictionary by using the combine function, but now I want to make a second function named people that will output all the names of the people with the age you enter.

For example: if I enter 21 into that function, it should output Bob since Bob is the only one that's 21 years old.

I just have no idea how to do this since the AGE isn't the key in my dictionary and I also can't use an integer as a key.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Niels Gorsel
  • 377
  • 2
  • 3
  • 9
  • You absolutely *can* use an integer as a dictionary key - it's hashable and immutable. – jonrsharpe Sep 18 '14 at 11:14
  • How would you deal with 2 people being 21? Also, see http://stackoverflow.com/questions/8023306/get-key-by-value-in-dictionary – fredtantini Sep 18 '14 at 12:52
  • Is `leeftijd` in `people()` a typo (missed translation) of `age`? (Google translate does translate 'leeftijd' to 'age'.) – Jonathan Leffler Sep 18 '14 at 12:52
  • 1
    AFAIK, if you don't just do a linear search through the dictionary, you'll have to maintain an inverse mapping (dictionary), which will need to maintain a list of keys for each value (as there are 2 eighteen year olds, 4 nineteen year olds, and 2 twenty year olds in the data). – Jonathan Leffler Sep 18 '14 at 12:55
  • 1
    If you find yourself wanting to do this, you are probably using the wrong datastructure. You should either invert the dictionary, or use a bidirectional dictionary. For example: https://pypi.python.org/pypi/bidict/ – Jörg W Mittag Sep 18 '14 at 19:48
  • Expanding on @JörgWMittag comment. Consider changing the data structure. You could save just one key per age and have a list of people with that age. e.g. `ppl = {18:['Cathy','Dan'], ...}`. querying would be trivial: `ppl[18]` – fluxens Apr 15 '19 at 17:50

6 Answers6

1

As I noted in a comment, AFAIK, if you don't just do a linear search through the dictionary, you'll have to maintain an inverse mapping (dictionary), which will need to maintain a list of keys for each value (as there are 2 eighteen year olds, 5 nineteen year olds, and 3 twenty year olds in the data).

This code includes a (general purpose) function reverse_dictionary() which takes a given dictionary and creates the reverse mapping from it. The name and age variable names in the function are a giveaway that I wrote it for this problem, but change them to key and value and the code works on any dictionary where the values are hashable.

NAMES = ['Alice', 'Bob', 'Cathy', 'Dan', 'Ed', 'Frank',
         'Gary', 'Helen', 'Irene', 'Jack', 'Kelly', 'Larry']

AGES = [20, 21, 18, 18, 19, 20, 20, 19, 19, 19, 22, 19]

def reverse_dictionary(fwd):
    rev = {}
    for name, age in fwd.items():
        if age not in rev:
            rev[age] = []
        rev[age].append(name)
    return rev

def combine(list1,list2):
    dictionary = dict(zip(list1,list2))
    return dictionary

def people(age, dictionary):
    if age not in dictionary:
        return []
    return dictionary[age]

name_age = combine(NAMES, AGES)
print name_age

age_name = reverse_dictionary(name_age)

for age in range(17, 24):
    print age, people(age, age_name)

Sample output:

{'Ed': 19, 'Dan': 18, 'Gary': 20, 'Alice': 20, 'Kelly': 22, 'Larry': 19, 'Jack': 19, 'Frank': 20, 'Cathy': 18, 'Bob': 21, 'Irene': 19, 'Helen': 19}
17 []
18 ['Dan', 'Cathy']
19 ['Ed', 'Larry', 'Jack', 'Irene', 'Helen']
20 ['Gary', 'Alice', 'Frank']
21 ['Bob']
22 ['Kelly']
23 []

Note that this does not keep the two dictionaries synchronized; if you add a new name and age to the name_age dictionary, you'd also need to add the age and name to the reverse dictionary. On the other hand, if you load the name/age map once and it then remains stable and you need to do multiple lookups based on age, then the reversed dictionary is potentially much more efficient than a solution that iterates through the name/age dictionary for each search.

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
0

Actually there is no way as far as I know.

Just iterate through your dict:

people_array = combine(NAMES, AGES)
def people(age):
    for person in people_array:
        if people_array[person] == age:
            print(person)
Igl3
  • 4,900
  • 5
  • 35
  • 69
0

It can be done this way

for name, age in mydict.items():
    if age == search_age:
        print name
Omair Shamshir
  • 2,126
  • 13
  • 23
0

Try this function (key_for_value):

def key_for_value(d, value):
    for k, v in d.iteritems():
        if v == value:
            return k
    raise ValueError("{!r} not found".format(value))


mydict = {1: "a", 2: "b", 3: "c"}

print key_for_value(mydict, "a")
print key_for_value(mydict, "d")
codeape
  • 97,830
  • 24
  • 159
  • 188
0

A nice way to do it would be:

def people(age):
    ages = [i for i,j in enumerate(combine.values()) if j == age]
    return [combine.keys()[i] for i in ages]
Amit
  • 1
0

try this:

def people(age):
    return map(lambda x: x[0], filter(lambda x: x[1]==age, dictionary.items()))
Jason Hu
  • 6,239
  • 1
  • 20
  • 41