Reputation: 3
I'm stuck on a problem from a bootcamp prep course. The problem wants me to use a function that takes in a dictionary as an argument, checks the type of the value of one of the keys, and then updates that value if the condition is met. This function works great when it's given a specific list element from a list of dictionaries.
The trouble comes when i try to nest this function into a map to apply the function to the entire list of dictionaries instead of passing in one specific element.
I've tried giving the function as the first map argument without parentheses, as was demonstrated to me in the preceding materials, and then i've tried setting the iterator as the base list of dictionaries with no index, as a [:] slice, as a [0:len{list)] slice, as a [0:2] slice, all to no avail.
# list of dictionaries to be updated, trimmed to 3 for brevity
restaurants = [{'name': 'Fork & Fig',
'price': '$$',
'is_closed': False,
'review_count': 610},
{'name': 'Salt And Board',
'price': '$$',
'is_closed': False,
'review_count': 11},
{'name': 'Stripes Biscuit',
'price': '$$',
'is_closed': True,
'review_count': 20}]
#function in question, changes the $ strings to numbers
def format_restaurant(restaurant):
if type(restaurant['price']) == str:
restaurant['price'] = len(restaurant['price'])
return restaurant
# inputting a single dictionary entry works great:
format_restaurant(restaurants[1]) # {'is_closed': False, 'name': 'Fork & Fig', 'price': 2, 'review_count': 610}
# Here comes the sticking point. The directions are:
#"Now write another function called map_format_restaurants using map, that
# uses above function and returns a list of restaurants with each of them
# formatted with price pointing to the respective number."
# My answer that I think should work, but doesn't:
def map_format_restaurants(restaurants):
map(format_restaurant, restaurants)
return restaurants
# When this function is called, the list of dictionaries comes out just as it went in:
map_format_restaurants(restaurants)
I want the code to change the '$' to 1 or the '$$' to 2 for each 'price' key value in the list of dictionaries, but none of them change. No error messages are thrown.
looking at the last dict entry in the list:
{'name': 'Stripes Biscuit',
'price': '$$',
'is_closed': True,
'review_count': 20}]
should have changed to:
{'name': 'Stripes Biscuit',
'price': 2,
'is_closed': True,
'review_count': 20}]
but instead came out just like it went in.
I'm sure this is a nice softball for someone out there, but I can't seem to hit it. Any insights would be greatly appreciated.
Upvotes: 0
Views: 1681
Reputation: 114330
In Python 3, map
is a lazy generator. It only runs the function when you consume it, i.e., when you ask it for elements. Until that happens, it just sits there as a map
object, waiting.
One fairly standard way to consume a map
is to build a list
from it:
def map_format_restaurants(restaurants):
return list(map(format_restaurant, restaurants))
Remember that this creates an entirely new list, but also modifies the existing list in-place. That means that you don't need to build a new list, and can use the fastest method I know if consuming iterators only for side-effects:
from collections import deque
deque(map(format_restaurant, restaurants), maxlen=0)
The maxlen
parameter ensures that the deque
stays empty as it consumes the iterator.
However, given that you are modifying everything in-place, having a return value for format_restaurant
is somewhat unpythonic. I would recommend using a simple for
loop instead:
def format_restaurant(restaurant):
...
# no return value
for restaurant in restaurants:
format_restaurant(restaurant)
Upvotes: 2
Reputation: 83537
map()
builds a new list. It does not modify the existing list. So modify your function to this:
def map_format_restaurants(restaurants):
return map(format_restaurant, restaurants)
Similarly, you need to assign the return value from this function:
new_restaurants = map_format_restaurants(restaurants)
Upvotes: -1