views:

92

answers:

3

I understand that it's quite easy to check if a key is available in a dictionary, but what about certain values?

So, what I have here is a dictionary of lists where the key references a set of, for consistency's sake, strings. It would look a bit like this:

menu = {'breakfast':['soft-boiled eggs', 'hash brown', 'Earl Grey'], 
        'lunch':['pasta', 'soup'], 
        'dinner':['chips', 'beef stew', 'veggies']}

Now what I'd like to do is check if, say, 'chips' is in my menu and if so, I'd like to replace it with 'crusty bread'. I know I can try using 'chips' in menu['lunch'] or the same for breakfast, but what if I don't know when it's being served?

Extension

While this is harder to explain let's say we've a class called Food defined such:

class Food(object):
def __init__(self, meal):
    self.meal = meal
    self.ingredients = collections.defaultdict(set)
def __str__(self):
    return "%s" %(self.meal)

Here, meal will refer to either breakfast, lunch or dinner. And we have ingredients which is a dictionary of sets. 'potatoes' is an ingredient and when keyed we'll have the relevant dishes show up: hash browns, chips. As such, when I call print meal, menu[meal].ingredients for my function, I get the following result (this is only for breakfast since that's all I've put in):

breakfast defaultdict(<type 'set'>, {'potatoes': set(['chips', 'hash brown']), 'eggs': set(['omelette', 'hard-boiled', 'soft-boiled']), 'tea': set(['Assam', 'Earl Grey', 'English'])})

So this is basically what's available for breakfast for specific 'ingredients'.

Now, let's assume the worst has happened and I've run out of potatoes! What I'd like to do now is replace 'potatoes' with 'bread' under which I'll have the values/types 'roll', 'crusty', 'brown'. How would one go about doing that?

And to top things off, towards lunch-time, we run out of 'Assam' tea. Similar to the question before the Extension, how would I remove that (after checking to see if it existed in the first place)?

+2  A: 

Membership in menu is easy:

[k for k, v in menu.iteritems() if 'chips' in v]

Membership with defaultdict works exactly the same way since containment checking doesn't mutate it.

Ignacio Vazquez-Abrams
Is that a list comprehension you've used, by any chance?
Az
It is. Since there are multiple possible answers, we need some sort of a structure that will return them all.
Ignacio Vazquez-Abrams
A: 

One obvious way is to just go thru whole dict and replace the values but IMO it is better to design it so that it is easy to replace ingredients e.g. have a single object(may be singleton class) for each type of ingredient, so you can just replace the types on the fly e.g.

tea.remove('assam')

and it will affect all the places where tea was being referred. similarly you can keep track of the meals where tea was being used, in some kind of registry and update registry if you want to remove tea from all the meals or may be flag tea as deleted, or want to replace potato with bread, do that in registry, which in turn can ask each meal to do that

registry.replace(potato, bread)
Anurag Uniyal
A: 

It looks like the basic thing you're asking for is how to iterate through a dictionary -- once you have that, it's all basic stuff.

for key,value in mydict.iteritems():
    print "%s = %s" %(key, value)

now, to apply it directly to your situation:

for meal, food in menu.iteritems():
    if 'potatoes' in food.ingredients:
        del food.ingredients['potatoes']
        food.ingredients['bread'] = set(['roll', 'crusty', 'brown'])

'del' can be used to remove a key/value pair from a dictionary

Jared Forsyth