EECS 110 Lec 5 List Comprehensions Aleksandar Kuzmanovic

  • Slides: 49
Download presentation
EECS 110: Lec 5: List Comprehensions Aleksandar Kuzmanovic Northwestern University http: //networks. cs. northwestern.

EECS 110: Lec 5: List Comprehensions Aleksandar Kuzmanovic Northwestern University http: //networks. cs. northwestern. edu/EECS 110 -s 18/

EECS 110 today The building blocks of functional computing data, sequences conditionals recursion List

EECS 110 today The building blocks of functional computing data, sequences conditionals recursion List Comprehensions map and applications Homework 2 - this coming Sunday…! Homework 1 - submitted 3 problems 1 lab problem Tuesday 2 python problems

Recursion Examples def mymax(L): """ input: a NONEMPTY list, L output: L's maximum element

Recursion Examples def mymax(L): """ input: a NONEMPTY list, L output: L's maximum element """

Recursion Examples def mymax(L): """ input: a NONEMPTY list, L output: L's maximum element

Recursion Examples def mymax(L): """ input: a NONEMPTY list, L output: L's maximum element """ if len(L) == 1: return else:

Recursion Examples def mymax(L): """ input: a NONEMPTY list, L output: L's maximum element

Recursion Examples def mymax(L): """ input: a NONEMPTY list, L output: L's maximum element """ if len(L) == 1: return L[0] else: if L[0] < L[1]: return mymax( L[1: ] ) else: return mymax( L[0: 1] + L[2: ] )

mymax( [1, 7, 3, 42, 5] ) Behind the curtain…

mymax( [1, 7, 3, 42, 5] ) Behind the curtain…

"Quiz" on recursion def power(b, p): """ returns b to the p power using

"Quiz" on recursion def power(b, p): """ returns b to the p power using recursion, not ** inputs: ints b and p output: a float """ Handle negative values of p, as well. For example, power(5, -1) == 0. 2 def sajak(s): """ returns the number of vowels in the input string, s """ sajak('wheel of fortune') == 6 power(5, 2) == 25. 0 Want more power? Names: (or so)

def power(b, p): """ inputs: base b and power p (an int) implements: b**p

def power(b, p): """ inputs: base b and power p (an int) implements: b**p = b*b**(p-1) """ if p == 0: return if p > 0: return else: # p < 0 return

def power(b, p): """ inputs: base b and power p (an int) implements: b**p

def power(b, p): """ inputs: base b and power p (an int) implements: b**p = b*b**(p-1) """ if p == 0: return 1 if p > 0: return else: # p < 0 return

def power(b, p): """ inputs: base b and power p (an int) implements: b**p

def power(b, p): """ inputs: base b and power p (an int) implements: b**p = b*b**(p-1) """ if p == 0: return 1 if p > 0: return b*power(b, p-1) else: # p < 0 return

def power(b, p): """ inputs: base b and power p (an int) implements: b**p

def power(b, p): """ inputs: base b and power p (an int) implements: b**p = b*b**(p-1) """ if p == 0: return 1 if p > 0: return b*power(b, p-1) else: # p < 0 return 1/power(b, -1*p)

power(2, 3) behind the curtain

power(2, 3) behind the curtain

def sajak(s): Base case? when there are no letters, there are ZERO vowels Look

def sajak(s): Base case? when there are no letters, there are ZERO vowels Look at the initial character. Rec. step? if it is NOT a vowel, the answer is if it IS a vowel, the answer is

def sajak(s): Base case? when there are no letters, there are ZERO vowels Look

def sajak(s): Base case? when there are no letters, there are ZERO vowels Look at the initial character. Rec. step? if it is NOT a vowel, the answer is just the number of vowels in the rest of s if it IS a vowel, the answer is 1 + the number of vowels in the rest of s

def sajak(s): if len(s) == 0: return 0 else: Checking for a vowel: Try

def sajak(s): if len(s) == 0: return 0 else: Checking for a vowel: Try #1 Base Case

def sajak(s): if len(s) == 0: Base Case return 0 else: Checking for a

def sajak(s): if len(s) == 0: Base Case return 0 else: Checking for a vowel: Try #1 and or not same as in English! but each side has to be a complete boolean value!

def sajak(s): if len(s) == 0: Base Case return 0 else: if s[0] ==

def sajak(s): if len(s) == 0: Base Case return 0 else: if s[0] == 'a' or s[0] == 'e' or… Checking for a vowel: Try #1 and or not same as in English! but each side has to be a complete boolean value!

def sajak(s): if len(s) == 0: Base Case return 0 else: Checking for a

def sajak(s): if len(s) == 0: Base Case return 0 else: Checking for a vowel: Try #2 in

def sajak(s): if len(s) == 0: Base Case return 0 else: if s[0] not

def sajak(s): if len(s) == 0: Base Case return 0 else: if s[0] not in 'aeiou': Rec. Step return sajak(s[1: ]) else: if it is NOT a vowel, the answer is just the number of vowels in the rest of s return 1+sajak(s[1: ]) if it IS a vowel, the answer is 1 + the number of vowels in the rest of s

sajak('eerier') behind the curtain

sajak('eerier') behind the curtain

The key to understanding recursion is to first understand recursion… - advice from a

The key to understanding recursion is to first understand recursion… - advice from a student

functional programming >>> 'fun' in 'functional' True • representation via list structures (data) •

functional programming >>> 'fun' in 'functional' True • representation via list structures (data) • leverage self-similarity (recursion) • create small building blocks (functions) Compose these together to solve or investigate problems. Key ideas in functional programming elegant and concise vs. not maximally efficient for the computer…

return to recursion Composing functions into specific applications Creating general functions that will be

return to recursion Composing functions into specific applications Creating general functions that will be useful everywhere (or almost…)

return to recursion Composing functions into specific applications Creating general functions that will be

return to recursion Composing functions into specific applications Creating general functions that will be useful everywhere (or almost…) building blocks with which to compose…

sum, range def sum(L): """ input: a list of numbers, L output: L's sum

sum, range def sum(L): """ input: a list of numbers, L output: L's sum """

sum, range def sum(L): """ input: a list of numbers, L output: L's sum

sum, range def sum(L): """ input: a list of numbers, L output: L's sum Base Case """ if the input has no elements, its sum is zero if len(L) == 0: This input to the recursive call must be "smaller" somehow… return 0. 0 else: return L[0] + sum(L[1: ]) Recursive Case if L does have an element, add that element's value to the sum of the REST of the list…

sum, range def range(low, hi): """ input: two ints, low and hi output: int

sum, range def range(low, hi): """ input: two ints, low and hi output: int list from low up to hi """ excluding hi

sum, range def range(low, hi): """ input: two ints, low and hi output: int

sum, range def range(low, hi): """ input: two ints, low and hi output: int list from low up to hi """ if hi <= low: return [] else: return excluding hi

sum, range def range(low, hi): """ input: two ints, low and hi output: int

sum, range def range(low, hi): """ input: two ints, low and hi output: int list from low up to hi """ if hi <= low: return [] else: return [low] + range(low+1, hi) excluding hi

sum and range >>> sum(range(101)) Looks sort of scruffy for a 7 -year old…

sum and range >>> sum(range(101)) Looks sort of scruffy for a 7 -year old… ! and 100 more…

Recursion: Good News/Bad News Recursion is common (fundamental) in functional programming def dbl. List(L):

Recursion: Good News/Bad News Recursion is common (fundamental) in functional programming def dbl. List(L): """ Doubles all the values in a list. input: L, a list of numbers """ if L == []: return L else: return [L[0]*2] + dbl. List(L[1: ]) But you can sometimes hide it away!

Map: The recursion "alternative" def dbl(x): >>> map( dbl, [0, 1, 2, 3, 4,

Map: The recursion "alternative" def dbl(x): >>> map( dbl, [0, 1, 2, 3, 4, 5] ) [0, 2, 4, 6, 8, 10] return 2*x >>> map( sq, range(6) ) [0, 1, 4, 9, 16, 25] def sq(x): return x**2 (1) map always returns a list (2) map(f, L) calls f on each item in L def isana(x): return x=='a’ >>> map( isana, 'go away!' ) [0, 0, 0, 1, 0, 0] Hey… this looks a bit False to me!

Map ! def dbl. List(L): """ Doubles all the values in a list. input:

Map ! def dbl. List(L): """ Doubles all the values in a list. input: L, a list of numbers """ if L == []: return L else: return [L[0]*2] + dbl. List(L[1: ]) Without map def dbl(x): return x*2 def dbl. List(L): """ Doubles all the values in a list. input: L, a list of numbers """ return map(dbl, L) With map!

Map: a higher-order function In Python, functions can take other functions as input… def

Map: a higher-order function In Python, functions can take other functions as input… def map( f, L ): Key Concept Functions ARE data!

Why use map?

Why use map?

Why use map? More elegant / shorter code, “functional in style” Faster execution in

Why use map? More elegant / shorter code, “functional in style” Faster execution in Python – map optimized for operations in lists Avoid rewriting list recursion (build once, use lots)

Mapping without map: List Comprehensions Anything you want to happen to each element of

Mapping without map: List Comprehensions Anything you want to happen to each element of a list name that takes on the value of each element in turn any name is OK! input output the list (or string) >>> [ dbl(x) for x in [0, 1, 2, 3, 4, 5] ] [0, 2, 4, 6, 8, 10] >>> [ x**2 for x in range(6) ] [0, 1, 4, 9, 16, 25] >>> [ c == 'a' for c in 'go away!' ] [0, 0, 0, 1, 0, 0]

Mapping without map: List Comprehensions def dbl(x): return 2*x def sq(x): return x**2 def

Mapping without map: List Comprehensions def dbl(x): return 2*x def sq(x): return x**2 def isana(x): return x=='a’ >>> [0, map( dbl, [0, 1, 2, 3, 4, 5] ) 2, 4, 6, 8, 10] [ dbl(x) for x in [0, 1, 2, 3, 4, 5] ] 2, 4, 6, 8, 10] >>> [0, map( sq, range(6) ) 1, 4, 9, 16, 25] [ x**2 for x in range(6) ] 1, 4, 9, 16, 25] >>> [0, map( isana, 'go away!' ) 0, 0, 1, 0, 0] [ c == 'a' for c in 'go away!' ] 0, 0, 1, 0, 0]

List Comprehensions len(L) sajak(s) s. Score(s) scrabble score implemented via raw recursion def len(L):

List Comprehensions len(L) sajak(s) s. Score(s) scrabble score implemented via raw recursion def len(L): if L == []: return 0 else: return 1 + len(L[1: ]) def sajak(s): if len(s) == 0: return 0 else: if s[0] not in 'aeiou': return sajak(s[1: ]) else: return 1+sajak(s[1: ]) def s. Score(s): if len(s) == 0: return 0 else: return let. Score(s[0]) + s. Score(s[1: ])

List Comprehensions len(L) LC = [1 for x in L] return sum( LC )

List Comprehensions len(L) LC = [1 for x in L] return sum( LC )

List Comprehensions len(L) LC = [1 for x in L] return sum( LC )

List Comprehensions len(L) LC = [1 for x in L] return sum( LC ) sajak(s) # of vowels LC = [c in 'aeiou' for c in s] return sum( LC )

List Comprehensions len(L) LC = [1 for x in L] return sum( LC )

List Comprehensions len(L) LC = [1 for x in L] return sum( LC ) sajak(s) # of vowels LC = [c in 'aeiou' for c in s] return sum( LC ) s. Score(s) scrabble score LC = [ let. Score(c) for c in s] return sum( LC )

Quiz Write each of these functions concisely using list comprehensions… Write def count(e, L):

Quiz Write each of these functions concisely using list comprehensions… Write def count(e, L): Write def lotto(Y, W): Name(s): input: e, any element L, any list or string output: the # of times L contains e example: count('f', 'fluff') == 3 Remember True == 1 and False == 0 W are the winning numbers input: Y and W, two lists of lottery numbers (ints) Y are your numbers output: the # of matches between Y & W example: lotto([5, 7, 42, 44], [3, 5, 7, 44]) == 3 Extra! Write def divs(N): input: N, an int >= 2 output: the number of positive divisors of N example: divs(12) == 6 (1, 2, 3, 4, 6, 12)

Quiz

Quiz

Quiz count(e, L) LC = [x==e for x in L] return sum( LC )

Quiz count(e, L) LC = [x==e for x in L] return sum( LC )

Quiz lotto(Y, W) LC = [c in Y for c in W] return sum(

Quiz lotto(Y, W) LC = [c in Y for c in W] return sum( LC )

Quiz divs(N) LC = [ N%c==0 for c in range(1, N+1)] return sum( LC

Quiz divs(N) LC = [ N%c==0 for c in range(1, N+1)] return sum( LC )

Quiz count(e, L) LC = [x==e for x in L] return sum( LC )

Quiz count(e, L) LC = [x==e for x in L] return sum( LC ) lotto(Y, W) LC = [c in Y for c in W] return sum( LC ) divs(N) LC = [ N%c==0 for c in range(1, N+1)] return sum( LC )

See you at Lab!

See you at Lab!