Table of Contents:
Which of the following functions works for determining if val
is an element in aList
?
def isElementOf1(val, aList):
"""Version ONE for a list membership function.
"""
for elt in aList:
if elt==val:
return True
else:
return False
def isElementOf2(val, aList):
"""Version TWO for a list membership function.
"""
for elt in aList:
if elt==val:
return True
return False
def isElementOf3(val, aList):
"""Version THREE for a list membership function.
"""
for elt in aList:
if elt==val:
return True
return False
Let's test the behavior of each function with the given list:
animals = ["cat", "mouse", "dog", "rabbit"]
# Predict which of these will work before executing this cell
print("isElementOf1('mouse', animals) =>", isElementOf1('mouse', animals))
print("isElementOf2('mouse', animals) =>", isElementOf2('mouse', animals))
print("isElementOf3('mouse', animals) =>", isElementOf3('mouse', animals))
Here are some lists from the lecture slides that we have seen before:
primes = [2, 3, 5, 7, 11, 13, 17, 19] # List of primes less than 20
bools = [1<2, 1==2, 1>2]
houses = ['Gryffindor', 'Hufflepuff', 'Ravenclaw', 'Slytherin']
strings = ['ab' + 'cd', 'ma'*4]
people = ['Hermione Granger', 'Harry Potter',
'Ron Weasley', 'Luna Lovegood']
# A list of string lists
animalLists = [['duck', 'raccoon'],
['fox', 'raven', 'gosling'], [], ['turkey']]
# A heterogeneous list (values of different types)
stuff = [17, True, 'foo', None, [42, False, 'bar']]
empty = [] # An empty list
in
and not in
¶We will use Python's built-in in
and not in
operators rather than isElementOf
.
The in
operator simplifies functions such as isVowel
and isValidGesture
below:
def isVowel(char):
return len(char) == 1 and char.lower() in 'aeiou' # an example of using 'in' with a string
def isValidGesture(g):
return g in ['rock', 'paper', 'scissors'] # an example of using 'in' with a list
for c in 'ABcde':
print(c, ':', isVowel(c))
print()
for g in ['rock', 'paper', 'scissors', 'Spock', 'paepr', 'sissors']:
print(g, ':', isValidGesture(g))
in
¶Use in
with lists and to check for substrings in strings.
Predict what each of the calls to testIn
will do.
def testIn(thing, collection):
print(thing, 'in', collection, '=>', thing in collection)
testIn('Ravenclaw', houses)
testIn('Munger', houses)
testIn('Hermione Granger', people)
testIn('Hermione', people)
testIn('m', 'Hermione Granger')
testIn('x', 'Hermione Granger')
testIn('anger', 'Hermione Granger')
testIn('oneG', 'Hermione Granger')
testIn('one G', 'Hermione Granger')
testIn([2, 3], [1, 2, 3, 4])
Look at this concise way of testing for multiple substrings at once
for string in ['e', 'x', 'Hermione', 'oneG', 'one G']:
print(string, ':', string in 'Hermione Granger')
In previous lectures we have seen that it is common to use loops in conjunction with accumulating variables that accumulate results from processing elements within the loop.
Below are examples of functions with while
and for
loops that accumulate a sum in a number variable.
def sumHalves(n):
'''Sum the positive successive halves of n'''
sumSoFar = 0 # initialize accumulator variable
while (n > 0):
sumSoFar += n
n = n//2
return sumSoFar
sumHalves(22)
def sumList(nums):
sumSoFar = 0 # initialize accumulator variable
for n in nums:
sumSoFar += n
return sumSoFar
sumList([8, 3, 10, 4, 5])
In this lecture, we focus on loops in which the value that's accumulated is a list.
We can create new lists through accumulation, for example, a list of a number and its halves (see slide 6).
def halves(n):
"""Returns a list of successive halves created from n."""
result = [] # 1. initialize accumulator for list
while (n > 0):
result.append(n) # 2. update list accumulator by adding item to end
n = n//2 # 3. make n smaller
return result # 4. return accumulator
halves(22)
Alternatively, we can use list concatentation to add an item to the end of a list:
def halvesAlt(n):
"""Returns a list of successive halves created from n."""
result = [] # 1. initialize accumulator for list
while (n > 0):
result += [n] # 2. update list accumulator by adding item to end
n = n//2 # 3. make n smaller
return result # 4. return accumulator
halves(22)
We can have more than one accumulation happening at the same time, as shown in the function below, which accumulate into a list the intermediate results accumulated in the numeric sumSoFar
variable:
def partialSums(nums):
"""Returns a list of partial sums from a given list.
"""
# initialize accumulators
sumSoFar = 0
partials = []
# continously update the accumulators
for n in nums:
sumSoFar += n
partials.append(sumSoFar)
return partials
partialSums([8, 3, 10, 4, 5])
prefixes
¶Write a function named prefixes()
that, given a string, returns a list of nonempty prefixes of the string,
ordered from shortest to longest.
prefixes('Python')
--> ['P','Py','Pyt','Pyth’,'Pytho’,'Python']
def prefixes(phrase):
"""Given a string, returns a list of nonempty prefixes of the string,
ordered from shortest to longest.
"""
# Flesh out this function body
# Your code here
prefixList = [] # accumulator to hold final result as a list
prefixSoFar = '' # accumulator to hold string value
for char in phrase:
prefixSoFar += char
prefixList.append(prefixSoFar)
return prefixList
prefixes('Python')
prefixes('Constantinople')
prefixes('oh')
Given a list, we can generate a new list of the same length in which each element is the result of performing the same function on each element of the original list. This is called mapping the function over the list.
def mapDouble(nums):
"""Given a list of numbers, returns a *new* list,
in which each element is twice the corresponding
element in the input list.
"""
result = []
for n in nums:
result.append(2*n)
return result
# test mapDouble with a list of numbers.
mapDouble([42, 19, 57, 36])
mapSquare
¶Modify the function mapDouble
to become mapSquare
, and generate the list of squares for the numbers 1 to 10 (inclusive).
# define mapSquare by modifying mapDouble
def mapSquare(nums):
"""Given a list of numbers, returns a *new* list,
in which each element is the square of the corresponding
element in the input list.
"""
# Flesh out this function body
# Your code here
result = []
for n in nums:
result.append(n**2)
return result
# test mapSquare with a sequence of numbers from 1 to 10 inclusive,
# use range to generate the list
# Your code here
mapSquare(range(1, 11))
mapFirstWord
¶Write a function named mapFirstWord
, which takes a list of strings in which each string has words separated by spaces. It returns a new list of the first words in each string. E.g.
mapFirstWord((['feisty smelly dog',
'furry white bunny',
'orange clown fish'])
=> ['feisty', 'furry', 'orange']
Reminder: The string method split
can split a string into words at spaces.
def mapFirstWord(strings):
""" Given a list of (possibly multiword) strings,
returns a new list in which each element is the first word
of the corresponding string in the input list.
"""
# Flesh out this function body
# Your code here
firstWords = []
for word in strings:
first = word.split()[0]
firstWords.append(first)
return firstWords
mapFirstWord (['feisty smelly dog', 'furry white bunny', 'orange clown fish'])
mapFirstWord(people)
Another common way to produce a new list is to filter an existing list, returning a new list that contains only those elements from the original one that satisfy a certain predicate. This is the filtering pattern.
For example, the filterEvens
pattern takes a list of integers and returns new list consisting of only the even numbers in the original list:
def filterEvens(nums):
"""Given a list of numbers, returns a *new* list of all
numbers in the input list that are divisible by 2.
"""
result = []
for n in nums:
if n%2 == 0:
result.append(n)
return result
NOTE: Before executing these cells, try to hypothesize what the output will be, then verify.
filterEvens([100, 21, 32, 44, 55, 71, 91, 23, 56])
filterEvens([2, 4, 6, 8])
filterEvens([11, 13, 15, 17, 19])
sameFirstLast
¶Define a function that takes a list of strings and retuns a new list of those strings that begin and end with the same letter. E.g.:
sameFirstLast("I saw a comic who told funny stories".split())
=> ['I', 'a', 'comic', 'stories']
def sameFirstLast(wordList):
"""Return a new list of all words in wordList that begin and end with the same letter.
"""
# Flesh out this function body
# Your code here
newList = []
for word in wordList:
if word[0] == word[-1]:
newList.append(word)
return newList
sameFirstLast("I saw a comic who told funny stories".split())
filterElementsContaining
¶Define a function that takes a string value and a list of strings and returns a new list of all the list elements that contain the string as a substring. E.g.:
filterElementsContaining('er', "The butcher, the baker, the candlestick maker".split())
=> ['butcher', 'baker', 'maker']
def filterElementsContaining(substring, stringList):
"""Return a new list whose elements are all the
elements of aList that contain val.
"""
# Flesh out this function body
# Your code here
newList = []
for string in stringList:
if substring in string:
newList.append(string)
return newList
filterElementsContaining('er', "The butcher, the baker, the candlestick maker".split())
filterElementsContaining('y',['hairy smelly dog', 'furry white bunny', 'orange clown fish'])
It's easy (and common) to combine the mapping and filtering patterns. E.g. supose we want to return the squares of all the even numbers in a list of integers:
def squaresOfEvens(nums):
newList = []
for num in nums:
if num % 2 == 0: # keep only the evens
newList.append(num*num) # square each of the evens
return newList
squaresOfEvens(range(1,11))