Reputation: 37
Take, for instance this dictionary of minerals, and foods that contain those minerals as mineral:food key:value pairs (D)-
D = {'copper': {'Tomatoes', 'Onions', 'Eggplant', 'Grapes', 'Bell Peppers'}, 'manganese': {'Tomatoes', 'Onions', 'Eggplant', 'Grapes', 'Garlic', 'Celery', 'Bell Peppers'}, 'magnesium': {'Onions'}, 'phosphorus': {'Onions'}, 'potassium': {'Celery', 'Tomatoes', 'Grapes'}, 'sodium': {'Celery', 'Butter'}, 'salt': {'Celery', 'Butter'}}
I'm trying to write a function (I'm assuming now a regular expression), that takes a string of 3 minerals, and returns a set of the foods that contain those minerals.
For instance, for the input: 'copper & manganese & phosphorus'
I would need the output to be: {Onions}
Because onions are the only food that contain all 3 minerals. (Using AND (not OR) logic).
So I need to check the dictionary only for keys that contain all 3 values.
Right now I was able to come up with the following, which does what I want, only using "OR" logic. As in, it returns all of the keys that contain any of those values.
D = {'copper': {'Tomatoes', 'Onions', 'Bell Peppers', 'Eggplant', 'Grapes'}, 'manganese': {'Tomatoes', 'Onions', 'Bell Peppers', 'Celery', 'Eggplant', 'Garlic', 'Grapes'}, 'magnesium': {'Onions'}, 'phosphorus': {'Onions'}, 'potassium': {'Tomatoes', 'Celery', 'Grapes'}, 'sodium': {'Butter', 'Celery'}, 'salt': {'Butter', 'Celery'}}
mList = ['copper', 'magnesium', 'manganese', 'phosphorus', 'potassium', 'salt', 'sodium']
x = []
y = [D[k] for k in mList if k in D]
for s in y:
for r in s:
if r not in x:
x.append(r)
x = sorted(x)
sx = set(x)
return(sx)
Returns:
{'Tomatoes', 'Onions', 'Bell Peppers', 'Celery', 'Eggplant', 'Garlic', 'Grapes'}
Upvotes: 0
Views: 109
Reputation: 4238
As Matt noted, Python sets allow you to perform calculations based on set theory: in this case, to check for the intersection (or overlaps) between sets.
D = {'copper': {'Tomatoes', 'Onions', 'Bell Peppers', 'Eggplant',
'Grapes'},
'manganese': {'Tomatoes', 'Onions', 'Bell Peppers', 'Celery',
'Eggplant', 'Garlic', 'Grapes'},
'magnesium': {'Onions'},
'phosphorus': {'Onions'},
'potassium': {'Tomatoes', 'Celery', 'Grapes'},
'sodium': {'Butter', 'Celery'},
'salt': {'Butter', 'Celery'}}
Based on the dictionary above, a function that accepts three arguments can calculate and return the intersection of three of the sets stored in the dictionary:
def food_intersection(3_mineral_string, D):
food1, food2, food3 = 3_mineral_string.split('_')
# i.e. 'copper_magnesium_phosphorus'
# The split function creates a list w/ 3 elements
# that list can be immediately 'unpacked'
# and each element can be associated w/ a
# separate variable (i.e. food1)
# Your technique (in the comments) of breaking out the
# list items via index: food1 = myList[0]
# also can work.
# food1, food2, food3 = 3_mineral_string.split()
# we can do this if the food string is
# separated by spaces instead.
return D[food1] & D[food2] & D[food3]
Calling this, with your sample foods:
food_intersection('copper_magnesium_phosphorus', D)
yields:
{'Onions'}
In the above function the &
operator tells Python to call the .intersection()
method on a set.
Since D[food*]
returns a set for each food we input, we are simply using the &
operator to OR all the sets leaving only the values that are present in each set.
Lucky for us, Python allows us to chain all of these on a single line.
Upvotes: 0
Reputation: 11
So just to expand from this answer a little bit, you can simply use intersections of the sets.
The ampersand operator will give you the intersections of those sets, ie any items that those sets all have in common.
>>> D["copper"] & D["magnesium"]
{'Onions'}
Which is really just a shorthand for:
>>> D["copper"].intersection( D["magnesium"] )
{'Onions'}
And going a step further, you can combine three of them:
>>> D["copper"] & D["manganese"] & D["phosphorus"]
{'Onions'}
It should be simple enough for you to use the inputs as the dictionary keys for the lookups!
Upvotes: 1