chrised209
chrised209

Reputation: 3

Using map (but not lambda) to update dict values in a list of dictionaries

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

Answers (2)

Mad Physicist
Mad Physicist

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

Code-Apprentice
Code-Apprentice

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

Related Questions