Playing with Snakes

Chapter 9: Storing Lots of Data: Lists

“A computer once beat me at chess, but it was no match for me at kick boxing.”
-Emo Philips

So last chapter we took care of finding a way to store our zombies. That's a good first step for our Zombie Uprising simulator. What's next?

When my wife and I sat down and drew up our emergency zombie uprising plan, we immediately made a list of supplies we'd need. I suggest you do the same. We could store these in a dictionary:

  1. supplies["item1"] = "food"
  2. supplies["item2"] = "water"
  3. supplies["item3"] = "Zombie movie collection"

Seems pointless to be storing those keys, doesn't it?

There's another solution. Instead of using String keys, we could use automatically created numeric keys. Here's part of a program to ask a user what supplies they think they should grab:

  1. supplies = []
  2. print "Press 'q' when you're done entering items"
  3. while True:
  4.     item = raw_input("Enter next item: ")
  5.     if item == 'q':
  6.         break
  7.     supplies.append(raw_input(item)

We're creating an empty list that we call supplies, up on line 1. We add items to it using the append() function. append() does exactly as you'd think it does: it add something on to the end of the list. This gives us order. No matter how many times we call print supplies, Python will always print:

['food', 'water', 'Zombie movie collection'] 

Printing a List

The only weird thing is that calling print directly on supplies will print out supplies as a list - not simply print out the items in supplies. If we wanted our list to look a little prettier, we'd have to add a loop to print the values of the list.

  1. for i in supplies:
  2.     print i,
food, water, Zombie movie collection

In the above example, i is getting each value in the list supplies. If we need, we can instead loop through the keys. The first key of any list is always 0 (computer scientists have this weird desire to always start counting at 0 - notice the way the chapters of this book are numbered). If you wanted to get the keys of this list, you'd just generate another list: all the numbers from 0 to 1 less than the number of items in the list. You can do that with the range() and len() functions.

  1. for i in range(0,len(supplies)):
  2.     print supplies[i]

len() simply finds the length of supplies. This little bit of Python will print the same as our previous example did:

food, water, Zombie movie collection

One confusing thing about len() is that while your list has len() items in it, the last item is at key len()-1. That is, if your list has 5 items in it, the last one is at key 4. Think about this as an example. Given the list ['a','b','c','d','e'], you and I both know there are 5 things in there. So len() will return 5. But the keys will be the numbers 0, 1, 2, 3, and 4.

Deleting items from a list

So I've realized that it's probably a bad idea to bring a Zombie movie collection, since after the uprising there might not be any power. So I want to remove it from my list. If I know the key, this is easy.

  1. print supplies
  2. del(supplies[2])
  3. print supplies

del() will have removed the last item:

['food', 'water', 'Zombie movie collection'] 
['food', 'water'] 

Slicing a list

Sometimes you don't want to look at an entire list, you just want to get chunks. You can do this by slicing the list. Let's make a new list for a simple example:

  1. our_list = range(0,10)

We could split our list up like this:

  1. our_list = range(0,10)
  2. first_two = ourlist[:2]
  3. next_two = ourlist[2:4]
  4. the_rest = ourlist[4:]

Now first_two is the list [0,1], next_two is the list [2,3], and the_rest is the list [4,5,6,7,8,9]. When slicing, you put two numbers in the square brackets. If you leave the first one out, Python assumes you meant to put a 0 there. If you leave the last one out, Python assumes you wanted to put in the length of your list. Each slice starts at the first number you put in, and goes until the key that is one less than the second number you put in.

This can be pretty handy if you need to do something quickly, like split a list in half. Say that I add a few items to our existing list of supplies, and then we'll let you carry half and me carry half:

  1. supplies = ['food','water','zombie repellent','tent','chainsaw']
  2. yourList = supplies[:len(supplies)/2]
  3. myList = supplies[len(supplies)/2]

This isn't a perfect method of splitting a list though, since if there's an odd number of items the second person will always end up with one more item than the first. But it works if you just need something quick.

A practical example might be something like this programming assignment I used to give:

Given a list, determine if it is balanced. A balanced list is definied as one where a point exists where you can split the list and have the sum of the left half be equal to the sum of the right half. For example, the list [2,3,4,1] is balanced, since you could split it down the middle. But the list [7,2,1,1] is not balanced.

Slicing makes solving this problem easy:

  1. #assuming the inputted list is stored in the list numbers
  2. found == False
  3. for i in range(len(numbers)):
  4.     if sum(numbers[:i]) == sum(numbers[i:]):
  5.         found = True
  6.         break
  7. if found == True:
  8.     print "Your list was balanced!"
  9. else:
  10.     print "Your list was not balanced"

This website will be taken offline before the end of 2011