# [Tutor] Fastest find in 2 2D lists with else statement

Steven D'Aprano steve at pearwood.info
Sat Mar 21 03:06:27 CET 2015

```On Fri, Mar 20, 2015 at 08:22:03AM -0400, Kale Good wrote:
> Hello all,
> I'm new to python and a bit of a weekend-warrior programmer (guitar
> teacher by trade), so there are plenty of computer sciencey concepts
> that I haven't grasped yet, and I think I'm bumping up against those now.
>
> Read from separate csv files, I have something like
>
>     a=[['bass',9],['eagle',36],['human',68]]
>     b=[['bass','fish'],['eagle','bird'],['dog',land']]
>     c=[[1,'fish','water'],[2, 'mammal','land'],[3,'bird','air']]

What do the numbers 9, 36, 68 in "a" list mean?

If I'm reading "b" correctly, you say a bass is a fish, an eagle is a
bird, and a dog is a land.

What do the numbers 1, 2, 3 in "c" list mean?

> What I want is to return where each animal lives. What I've been able to
> glisten from the manuals and stack overflow is:

Let's start by writing in English how you would do this. My guess is:

For each animal:
find out what kind of animal it is;
then look up where that kind of animal lives.

This tells you that the most natural sort of information you want is a
list of animals:

# [...] is used for lists
animals = ["bass", "eagle", "human", "spider", "salmon"]

plus a dict that associates each animal with its kind:

# {...} is used for dicts
kinds = {"bass": "fish",
"eagle": "bird",
"human": "mammal",
"spider": "arachnid",
"salmon": "fish",
}

plus a second dict that maps each kind to a location:

locations = {"fish": "water",
"bird": "air",
"mammal": "land",
"insect": "land",
"arachnid": "land",
"mollusk": "water",
}

Then your code becomes trivially easy!

for animal in animals:
kind = kinds[animal]
print(animal, "lives in or on", locations[kind])

The dict lookup kinds[animal] takes care of all the searching for you,
no need to write a for loop at all.

To handle the case where the animal or kind is unknown:

for animal in animals:
kind = kinds.get(animal, None)
if kind is None:
# Ask the user what sort of kind of animal it is.
# In Python 2, you MUST use raw_input instead of input!
kind = input("What kind of animal is '%s'?" % animal)
kind = kind.strip().lower()
kinds[animal] = kind
location = locations.get(kind, None)
if location is None:
# Ask the user where this kind of animal lives.
# In Python 2, you MUST use raw_input instead of input!
location = input("Where do '%s' animals live?" % kind)
location = location.strip().lower()
locations[kind] = location
print(animal, "lives in or on", location)

Note that direct lookups into a dict are written with square brackets:

kinds[animal]

but optional lookups with a default value use round brackets
(parentheses):

kinds.get(animal, None)  # None is the default.

Also, there's nothing you can write in Python which will be faster than
looking it up in a dict. If you have concerns about looping over lists
repeatedly, you are right to worry about speed. But if you can get the
same data into a dict or two, dict lookups are *blazingly* fast.

Are you able to move your data into the list and dictionary formats
shown above? The secret to programming successfully is that getting the
data into the right format is half the battle. Once you have the data in
the right format, everything else becomes so much simpler.

For example, I might take your "a" list and convert it like this:

a=[['bass',9],['eagle',36],['human',68]]
animals = [sublist[0] for sublist in a]

That extracts out the strings "bass", "eagle" etc. and puts them into a
list called "animals".

Converting your "b" list to a dict should be even easier:

b=[['bass', 'fish'],['eagle', 'bird'],['dog', 'mammal']]
kinds = dict(b)

Can you work out how to get the locations you need, or do you need more
help? Feel free to ask any questions you have!

--
Steve
```