Reputation: 681
in my list:
animals = [ ['dog', ['bite'] ],
['cat', ['bite', 'scratch'] ],
['bird', ['peck', 'bite'] ], ]
add('bird', 'peck')
add('bird', 'screech')
add('turtle', 'hide')
The add function should check that the animal and action haven't been added before adding them to the list. Is there a way to accomplish this without nesting a loop for each step into the list?
Upvotes: 2
Views: 4644
Reputation: 42193
While I agree with the others re. your choice of data structure, here is an answer to your question:
def add(name, action):
for animal in animals:
if animal[0] == name:
if action not in animal[1]:
animal[1].append(action)
return
else:
animals.append([name, [action]])
The for
loop is an inevitable consequence of your data structure, which is why everyone is advising you to consider dictionaries instead.
Upvotes: 0
Reputation: 86124
You're using the wrong data type. Use a dict
of set
s instead:
def add(key, value, userdict):
userdict.setdefault(key, set())
userdict[key].add(value)
Usage:
animaldict = {}
add('bird', 'peck', animaldict)
add('bird', 'screech', animaldict)
add('turtle', 'hide', animaldict)
Upvotes: 6
Reputation: 131640
Based on recursive's solution, in Python 2.5 or newer you can use the defaultdict
class, something like this:
from collections import defaultdict
a = defaultdict(set)
def add(animal, behavior):
a[animal].add(behavior)
add('bird', 'peck')
add('bird', 'screech')
add('turtle', 'hide')
Upvotes: 4
Reputation: 15845
animals_dict = dict(animals)
def add(key, action):
animals_dict.setdefault(key, [])
if action not in animals_dict[key]:
animals_dict[key].append(action)
(Updated to use setdefault
- nice one @recursive)
Upvotes: 0
Reputation: 126145
You really should use a dictionary for this purpose. Or alternatively a class Animal
.
You could improve your code like this:
if not any((animal[0] == "bird") for animal in animals):
# append "bird" to animals
Upvotes: 0
Reputation: 98002
While it is possible to construct a generic function that finds the animal in the list using a.index or testing with "dog" in animals, you really want a dictionary here, otherwise the add function will scale abysmally as more animals are added:
animals = {'dog':set(['bite']),
'cat':set(['bite', 'scratch'])}
You can then "one-shot" the add function using setdefault:
animals.setdefault('dog', set()).add('bite')
It will create the 'dog' key if it doesn't exist, and since setdefault returns the set that either exists or was just created, you can then add the bite action. Sets ensure that there are no duplicates automatically.
Upvotes: 4