0

so I am writing a program that when you give it a dictionary value it turns you it's key . the program consist of by giving the score of an allergy it tells you what allergy you got . I wrote the script but returns me None as result to my function . Can someone tell me what I should modify ?

def allergie(aller):
    listofallergies = {'eggs': 1 , 'peanuts':2 ,'shellfish': 4 , 'strawberries':8 , 'tomatoes': 16 , 'chocolat':32 , 'pollen': 64 , 'cats': 128 }
    if aller in listofallergies:
        print (listofallergies.keys(aller))
    else:
        return None 
print (allergie(4)) 
L3viathan
  • 26,748
  • 2
  • 58
  • 81
  • `print (listofallergies.keys(aller))` --> `return listofallergies.keys(aller)` – balderman Nov 07 '21 at 18:27
  • 2
    A comment on naming practice: if something is not a list don't call it a list. Call it `allgergies_dict` or something like that. – navneethc Nov 07 '21 at 18:29
  • 3
    I find it suspicious that the values are all powers of two: Isn't this a bit-map, and you can be given e.g. `5` for "shellfish and eggs"? – L3viathan Nov 07 '21 at 18:32

5 Answers5

2

You don't return anything if aller in listofallergies, just print. Also, aller in listofallergies will never be True, because that's not how you check if something is in the .values() of a dict.

Returning None is also not necessary if it is not in the dict — a function will return that automatically by default.

Since some_dict.keys() doesn't take an argument, as you seem to assume, you will need to iterate over all values and check if they are equal to the given value.

Here's how you could fix it:

def allergie(aller):
    listofallergies = {'eggs': 1 , 'peanuts':2 ,'shellfish': 4 , 'strawberries':8 , 'tomatoes': 16 , 'chocolat':32 , 'pollen': 64 , 'cats': 128 }
    if aller in listofallergies.values():
        for key, item in listofallergies.items():
            if item == aller:
                return key  # we found it, so we return it.

Frankly, you could also skip checking if aller in listofallergies.values() entirely, but maybe it's clearer this way.


If there's no good reason not to do this, why don't you just invert the dictionary? Then the function just becomes:

def allergie(aller):
    return {1: "eggs", 2: "peanuts", 4: "shellfish", ...}.get(aller)

Finally, if this is indeed a bitmap, and you want to in fact return the list of allergies encoded in a given value, you can do so with bitwise arithmetics:

def allergies(allergy_code):
    result = []
    for index, allergy in enumerate(['eggs', 'peanuts','shellfish', 'strawberries', 'tomatoes', 'chocolat', 'pollen', 'cats']):
        if allergy_code & 2**index:
            result.append(allergy)
    return result

>>> allergies(5)
['eggs', 'shellfish']
L3viathan
  • 26,748
  • 2
  • 58
  • 81
1

One problem would be that first if branch doesn't return nothing, it only prints. Secondly the logic is wrong if item in dict checks if item is a key in the dict, here as you have a value, you need to iterate on the pairs, to check the value and return the key if matches

def allergie(aller):
    listofallergies = {'eggs': 1, 'peanuts': 2, 'shellfish': 4, 'strawberries': 8,
                       'tomatoes': 16, 'chocolat': 32, 'pollen': 64, 'cats': 128}
    for key, value in listofallergies.items():
        if value == aller:
            return key
    return None

print(allergie(4))  # shellfish
print(allergie(40))  # None
azro
  • 53,056
  • 7
  • 34
  • 70
1

I would invert the dictionary once and then just use the dictionary get function with None as default:

listofallergies = {'eggs': 1 , 'peanuts':2 ,'shellfish': 4 , 'strawberries':8 , 'tomatoes': 16 , 'chocolat':32 , 'pollen': 64 , 'cats': 128 }
listofallergies_inv = {val: key for key, val in listofallergies.items()}

def allergie(aller):

    return listofallergies_inv.get(aller, None)
mcsoini
  • 6,280
  • 2
  • 15
  • 38
1

There are two problems with your code.

Problem 1

The first problem I see is when you want to check if aller is a value in your dictionary by doing the following,

dict_ex = {'a': 1, 'b': 2, 'c': 3}
print(2 in dict_ex)

The result of this is false because python will only look for 2 in the dictionaries keys. Same thing as saying 2 in ['a','b','c']

Instead, we can try and check if aller is in the dictionaries values specifically.

dict_ex = {'a': 1, 'b': 2, 'c': 3}
print(2 in dict_ex.values())

Problem 2

Problem number 2 is when you find the key of aller using print (listofallergies.keys(aller)). dict.keys() does not take a value. To find a key using a value you can do the following.

dict_ex = {'a': 1, 'b': 2, 'c': 3}
aller = 2
for k,v in dict_ex.items():
    if v == aller:
        print(k)

This will give us b.

Code

So your code fixed up...


def allergie(aller):
    listofallergies = {'eggs': 1 , 'peanuts':2 ,'shellfish': 4 , 'strawberries':8 , 'tomatoes': 16 , 'chocolat':32 , 'pollen': 64 , 'cats': 128 }
    if aller in listofallergies.values():
        for k,v in listofallergies.items():
            if v == aller:
                return k
    else:
        return None 
print (allergie(4)) 
Buddy Bob
  • 5,829
  • 1
  • 13
  • 44
0

Firstly, I recommend running this:

def allergie(aller):
    listofallergies = {'eggs': 1 , 'peanuts':2 ,'shellfish': 4 , 'strawberries':8 , 'tomatoes': 16 , 'chocolat':32 , 'pollen': 64 , 'cats': 128 }
    if aller in listofallergies:
        print("I am here")
        #print (listofallergies.keys(aller))    change this line
        return listofallergies[aller]
    else:
        return None 
print (allergie(4)) 

#output:
#None

This means the if block is never executed. Reason being you are checking if the value 4 is a key in the dictionary. Which it is not.

You can try the following

if aller in listofallergies.values()
    return listofallergies.keys()[listofallergies.values().index(aller)]
else:
return None

Alternatively, you xan use a dictionary that is the inverse of the on you have.

# if you want to create such a dictionary
alt_dict = {v: k for k, v in listofallergies.items()}

if aller in alt_dict:
    return alt_dict[aller]
else:
    return None
Muhd Mairaj
  • 557
  • 4
  • 13