Week 2, Friday: lists and strings, indexing and slicing

Assuming you have a list of names, like this:

L = ["jeff", "lisa", "lauri", "joshua"]

What is the difference between this for loop:

for i in range(len(L)):
  print(i)

and this for loop:

for i in L:
  print(i)

What does each for loop print? Try them out in the interactive python shell and make sure you understand the difference between each loop. Sometimes you just need the items from the list, and sometimes you need the position or index of each item in the list.

indexing

Using square-bracket indexing, we can access individual items in either a list or a string. For example:

>>> L = ["jeff", "lisa", "lauri", "joshua"]
>>> S = "Swarthmore"
>>> print(L[1])
lisa
>>> print(S[1])
w
>>> print(S[2])
a
>>> print(S[3])
r

strings are immutable, lists are mutable

In python, you can't change characters in a string, but you can change individual items in a list. For example, this works fine:

>>> L[1] = "PONY"
>>> print(L)
['jeff', 'PONY', 'lauri', 'joshua']

But this does not:

>>> S[2] = "Z"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment

You can, however, reassign to the same string variable:

>>> S = "SwZrthmore"
>>> print(S)
SwZrthmore

parallel lists and indexing

Suppose we have what are called parallel lists:

# parallel lists
players = ["Vladimir Radmanovic","Lou Williams","Lebron James", "Kevin Durant", \
  "Kobe Bryant","Kevin Garnett"]
ppg     = [0, 11.5, 30.3, 28.5, 30.0, 19.2]  # points-per-game
games   = [2, 13, 23, 20, 12, 20]            # games played

And we want to output the data for each player in a nice formatted table, like this:

0:  Vladimir Radmanovic  0.0  2
1:         Lou Williams 11.5 13
2:         Lebron James 30.3 23
3:         Kevin Durant 28.5 20
4:          Kobe Bryant 30.0 12
5:        Kevin Garnett 19.2 20

We can use indexing to get at data for each player, since they are parallel lists. And string formatting helps us line up the output:

for i in range(len(players)):
  print("%d: %20s %4.1f %2d" % (i, players[i], ppg[i], games[i]))

Notes:

slicing

Slicing allows you to quickly grab pieces out of a list or string. As a simple example, suppose you had variables for the first and last name of someone, and you wanted to create their ITS username (like hpotter1):

>>> first = "george"
>>> last = "washington"
>>> uname = first[0] + last[0:6] + "1"
>>> print(uname)
gwashin1

The 0:6 inside the square brackets means, give me everything from the 0th character (since it's a string) up to, but not including the character at index 6. For slicing, you can even specify a start:stop:step if you want. Here are some more examples:

>>> L = list("abcdefg")
>>> S = "we love comp sci!!"

>>> print(L)
['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> print(S)
we love comp sci!!

>>> print(L[0:len(L):2])
['a', 'c', 'e', 'g']

>>> print(S[:5])
we lo
>>> print(S[5:])
ve comp sci!!

>>> print(L[-1])   # last item
g
>>> print(S[-1])   # last char
!

Your Turn!

Can you write this silly program to get a string from the user, then display it split in half?

$ python splitphrase.py 

enter a string: we love computer science!!

we love compu
             t
             e
             r

             s
             c
             i
             e
             n
             c
             e
             !
             !

How about this one, to print out all single-character deletions of a word? That is, delete each letter, one at a time, and see what's left.

$ python deletions.py 

Input WORD: computer

Here's that word with all possible single-letter deletions: 
 0: omputer
 1: cmputer
 2: coputer
 3: comuter
 4: compter
 5: compuer
 6: computr
 7: compute