Section #7 Solutions
Written by Juliette Woodrow, Brahm Capoor, Anna Mistele, and John Dalloul
Using map
temps_F = [45.7, 55.3, 62.1, 75.4, 32.0, 0.0, 100.0]
#convert from Fahrenheit to Celsius
temps_C = list(map(lambda f : (f - 32) * 5 / 9, temps_F))
print('C: ', temps_C)
original_headings = [(30, 'N'), (359, 'N'), (340, 'N'), (270, 'W'), (124, 'E'), (149, 'S'), (219, 'S')]
def update_heading(reading):
updated_heading = (reading[0] + 22) % 360
updated_direction = calc_direction(updated_heading)
return (updated_heading, updated_direction)
def calc_direction(heading):
if 46 <= heading and heading <= 135:
return 'E'
elif 136 <= heading and heading <= 225:
return 'S'
elif 225 <= heading and heading <= 315:
return 'W'
else:
return 'N'
update_list = list(map(update_heading, original_headings))
print(update_list)
map(lambda word: word[::-1], text.split())
# OR
def reverse(s):
result = ""
for ch in s:
result = ch + result
return result
map(reverse, text.split())
def linear_transformation(vector, scale, shift):
"""
Takes in a vector (list of numbers), a scale factor, and a shift constant and returns the vector
where the ith term is equivalent to the ith term of the original vector multiplied by the scale
and added to the shift.
"""
# can set the lambda function to a variable to make code more readable
linear_transformation_fn = lambda x : scale * x + shift
result = list(map(linear_transformation_fn, vector))
return result
def convert_times(times):
conversion_factor = 1.25 * 1760 / 100 # divide total yards in 1.25 miles by 100 yards
return list(map(lambda x : x / conversion_factor, times))
Reading map
counting = [5, 6, 7, 8]
jenny = [8, 6, 7, 5, 3, 0]
map(lambda lst: lst.append(9), [counting, jenny])
# =>
"""
Whoa! Why does this iterable not contain anything? `map` replaces each
element with the *return* value of the function call. In this case, the
append function returns None, but modifies the value of the list... Tricky!
"""
counting = [5, 6, 7, 8]
jenny = [8, 6, 7, 5, 3, 0]
map(lambda lst: lst + [9], [counting, jenny])
# => <[5, 6, 7, 8, 9], [8, 6, 7, 5, 3, 0, 9]>
"""
This works as expected, because lst1 + lst2 *returns* a new list. In our
case, that's the original list, with the number 9 appended.
"""
Sorting with lambdas
>>> strs = ['apple', 'BANANA', 'candy', 'aardvark']
# 1.
>>> sorted(strs, key=lambda word : word.lower())
['aardvark', 'apple', 'BANANA', 'candy']
# 2.
>>> sorted(strs, key=lambda word : word.lower()[len(word)-1])
['BANANA', 'apple', 'aardvark', 'candy']
# 3.
>>> nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> sorted(nums, key=lambda num:abs(num-3.14))
[3, 4, 2, 5, 1, 6, 7, 8, 9, 10]
>>> min(nums, key=lambda num:abs(num-3.14))
3
>>> max(nums, key=lambda num:abs(num-3.14))
10
# 4A.
>>> sorted(rentals, key=lambda room_tuple:room_tuple[1])
[('elm st.', 1, 1200), ('pine st.', 2, 1600), ('main st.', 4, 4000)]
# 4B.
>>> sorted(rentals, key=lambda room_tuple:room_tuple[2])
[('elm st.', 1, 1200), ('pine st.', 2, 1600), ('main st.', 4, 4000)]
# 4C.
>>> sorted(rentals, key=lambda room_tuple:room_tuple[2]/room_tuple[1])
[('pine st.', 2, 1600), ('main st.', 4, 4000), ('elm st.', 1, 1200)]
>>> min(rentals, key=lambda room_tuple:room_tuple[2]/room_tuple[1])
('pine st.', 2, 1600)
Tweets Revisited
Part 1
def reverse_keys(flat_counts):
for pair in sorted(flat_counts.items(), reverse=True):
key = pair[0]
print(key)
def most_used(flat_counts):
"""
Given a non-empty "flat" counts dict of tags, return the tag
that has the largest count.
"""
sorted_tags = sorted(flat_counts.items(), key=lambda x: x[1], reverse=True)
print(sorted_tags[:10])
One Liners
-
Given list of non-empty strs, write a map/lambda and/or list comprehension to form a list of the strings in upper case.
>>> strs = ['Rhyme', 'Donut', '3xx', 'Orange'] # Map >>> list(map(lambda s: s.upper(), strs)) # List comprehension >>> [s.upper() for s in strs]
-
Given list of (x, y) points, write a sorted/lambda expression to order these points in decreasing order by the sum of the x+y of each point.
>>> points = [(10, 0), (1, 3), (3, 2), (5, 4)] >>> sorted(points, key=lambda pt: pt[0] + pt[1], reverse=True)
# a. Given a list of numbers.
# Call map() to produce a result where each
# number is multiplied by -1. (or equivalently write a comprehension)
>>> nums = [3, 0, -2, 5]
# yields [-3, 0, 2, -5]
# your expression:
map(lambda x: x*(-1), nums)
or
[num*(-1) for num in nums]
# b. Given a list of (x, y) "point" tuples where x and y are int values.
# Call map() to produce a result where each (x, y) is replaced
# by the sum of x and y. (or equivalently write a comprehension)
>>> points = [(1, 2), (4, 4), (1, 3)]
# yields [3, 8, 4]
# your expression:
map(lambda pt: pt[0]+pt[1], points)
or
[pt[0]+pt[1] for pt in points]
# c. Given a list of (city-name, zip-code, current-temperature) tuples, like this
>>> cities = [('modesto', 95351, 92), ('palo alto', 94301, 80), ...]
# Call sorted() to produce a list of these tuples sorted in decreasing
# order by temperature.
# your expression:
sorted(cities, key=lambda city: city[2], reverse=True)
# d. Given a non-empty list of (flower-name, scent-score, color-score) tuples
# like the following, scores are in the range 1 .. 10
>>> flowers = [('rose', 4, 8), ('orchid', 7, 2), ... ]
# Call max() or min() to return the flower tuple with the highest scent score.
# your expression:
max(flowers, key=lambda flower: flower[1])
Capstone CS106A Problems
Dict File problem from Winter Quarter Quiz #3
def read_posts(filename):
posts = {}
with open(filename) as f:
for line in f:
# could do .strip(), not marking off
words = line.split('^')
celeb = words[0]
for chan in words[1:]:
if chan not in posts:
posts[chan] = []
inner = posts[chan]
if celeb not in inner:
inner.append(celeb)
return posts
Prime Files
def prime_file(filename):
"""
The given file contains text data on each line as follows.
Each line is made of a mixture of non-empty alphabetic words
and non-negative ints, all separated by colons. The numbers can be distinguished
since their first char is a digit. Lines like this:
aaa:123:420:xyz:xxx:44:zz:a
The first element is the "prime" for that line, and is always alphabetic.
Read through all the lines and build a dict with a key for each prime,
and its value is a list of all the int number values from all the lines
with that prime.
Add every number to the list, even if it is a duplicate.
When all the data is loaded, print the primes in alphabetical order
1 per line, each followed by its sorted list of numbers, like this
aaa [44, 123, 123, 125, 420, 693]
bbb [16, 23, 101, 101]
"""
primes = {}
with open(filename) as f:
for line in f:
parts = line.split(':')
prime = parts[0]
# pick out which parts are ints - comprehension is cute here
# or could do this as a regular old for-loop with an append
# inside is fine and full credit.
nums = [int(part) for part in parts if part[0].isdigit()]
if not prime in primes:
primes[prime] = []
primes[prime].extend(nums)
# now output
for prime in sorted(primes.keys()):
print(prime, sorted(primes[prime]))
Dict File
def count_zips(filename):
states = {}
with open(filename) as f:
for line in f:
pass
words = line.split(',')
state = words[0]
if state not in states:
states[state] = {}
counts = states[state]
for word in words[1:]:
zip = word[:5]
if zip not in counts:
counts[zip] = 0
counts[zip] += 1
for state in sorted(states.keys()):
print(state)
counts = states[state]
for zip in sorted(counts.keys()):
print(zip, counts[zip])
Lightning
def parse_lightning(filename):
states = {}
with open(filename) as f:
for line in f:
pass
words = line.split(',')
i_state = len(words) - 1
state = words[i_state].strip() # not grading off: remove \n
if state not in states:
states[state] = []
nums = states[state] # decomp by var
for numstr in words[:i_state]: # omit last elem
nums.append(int(numstr))
for state in sorted(states.keys()):
print(state, states[state], sum(states[state]))
© Stanford 2020 | CS106A has been developed over decades by many talented teachers. Website designed by Chris Piech.