1

standings

[{'driver': 'Max Verstappen', 'team': 'Red Bull', 'home_country': 'Netherlands', 'points': 0}, {'driver': 'Lewis Hamilton', 'team': 'Mercedes', 'home_country': 'United Kingdom', 'points': 0}, {'driver': 'George Russell', 'team': 'Mercedes', 'home_country': 'United Kingdom', 'points': 0}, {'driver': 'Sergio Perez', 'team': 'Red Bull', 'home_country': 'Mexico', 'points': 0}, {'driver': 'Lando Norris', 'team': 'McLaren', 'home_country': 'United Kingdom', 'points': 0}, {'driver': 'Charles Leclerc', 'team': 'Ferrari', 'home_country': 'Monaco', 'points': 0}, {'driver': 'Valtteri Bottas', 'team': 'Ferrari', 'home_country': 'Spain', 'points': 0}]

driver_with_points

{'Carlos Sainz': 18, 'Charles Leclerc': 26, 'Esteban Ocon': 6, 'Fernando Alonso': 2, 'George Russell': 12, 'Kevin Magnussen': 10, 'Lewis Hamilton': 15, 'Valtteri Bottas': 8, 'Yuki Tsunoda': 4, 'Zhou Guanyu': 1}

I have to update the standings list depending on the points of driver in driver_with_points dictionary, if driver name exists in driver_with_points dictionary.

The task is done simply by the following lines.

for driver in standings:
    if driver["driver"] in drivers_with_points.keys():
        driver["points"] = drivers_with_points[driver["driver"]]
    

But I need to do the similar task by using list comprehension.

Can anyone help me convert this for loop to list comprehension?

I have tried

[driver["points"]=drivers_with_points[driver["driver"]] for driver in standings if driver["driver"] in drivers_with_points.keys()]

but it's error Unresolved reference 'drivers_with_points

  • What do you mean "multiple dictionaries"? Please provide a [mre] that actually runs -- yours doesn't because 1. what is `standings`? 2. what is `drivers_with_points`? 3. Why do you expect that list comprehension to work? There's a syntax error. Also specify _what_ errors you're seeing. Do you go to a doctor and say "I'm feeling symptoms"? [ask] | [question checklist](//meta.stackoverflow.com/q/260648/843953) – Pranav Hosangadi Mar 29 '22 at 15:32
  • @PranavHosangadi I have edited the question. Please let me know if you could help? – Asad Kareem Mar 29 '22 at 15:41
  • A list / dict comprehension is for _buiding_ a list or dictionary from scratch. If you want to rebuild the entire `standings` list, you can use a list comprehension. Here, you just want to modify the existing list, and are trying to use a list comprehension for side-effects (you don't want to actually build a list, you're just trying to use it as a way to compress a loop into one line). Don't do that. A list comprehension isn't significantly faster than a regular loop. – Pranav Hosangadi Mar 29 '22 at 15:45
  • 1
    Why do you **need** to do this with a list comprehension? It makes no sense as you don't need a new list - i.e., you're just updating dictionaries within an existing list – DarkKnight Mar 29 '22 at 15:51
  • Actually, this is a school assignment. We have to do it by using list comprehension. – Asad Kareem Mar 29 '22 at 15:56
  • @AsadKareem You should talk to whoever set this assignment and enlighten them. – DarkKnight Mar 29 '22 at 15:59

2 Answers2

3

There is nothing wrong with doing this using a comprehension, but you shouldn't aim at updating an existing data structure. With a comprehension you should be making a new list rather than mutating the original. Comprehensions come from functional programming where immutable data is an aim.

You can use a list comprehension to make a new list which you can then assign to standings. One way to do this is by unpacking the original dict and replacing the points with either the value from driver_with_points or the original if not found. dict.get(key, some_default) is a good pattern for this.

Consider:

standings = [{'driver': 'Max Verstappen', 'team': 'Red Bull', 'home_country': 'Netherlands', 'points': 0}, {'driver': 'Lewis Hamilton', 'team': 'Mercedes', 'home_country': 'United Kingdom', 'points': 0}, {'driver': 'George Russell', 'team': 'Mercedes', 'home_country': 'United Kingdom', 'points': 0}, {'driver': 'Sergio Perez', 'team': 'Red Bull', 'home_country': 'Mexico', 'points': 0}, {'driver': 'Lando Norris', 'team': 'McLaren', 'home_country': 'United Kingdom', 'points': 0}, {'driver': 'Charles Leclerc', 'team': 'Ferrari', 'home_country': 'Monaco', 'points': 0}, {'driver': 'Valtteri Bottas', 'team': 'Ferrari', 'home_country': 'Spain', 'points': 0}]
drivers_with_points = {'Carlos Sainz': 18, 'Charles Leclerc': 26, 'Esteban Ocon': 6, 'Fernando Alonso': 2, 'George Russell': 12, 'Kevin Magnussen': 10, 'Lewis Hamilton': 15, 'Valtteri Bottas': 8, 'Yuki Tsunoda': 4, 'Zhou Guanyu': 1}

# make a new list with new dicts:
standings = [{**s, 'points': drivers_with_points.get(s['driver'], s['points'])} for s in standings]

This will give you a new list and assign it standings with:

[{'driver': 'Max Verstappen',
  'team': 'Red Bull',
  'home_country': 'Netherlands',
  'points': 0},
 {'driver': 'Lewis Hamilton',
  'team': 'Mercedes',
  'home_country': 'United Kingdom',
  'points': 15},
 {'driver': 'George Russell',
  'team': 'Mercedes',
  'home_country': 'United Kingdom',
  'points': 12},
 {'driver': 'Sergio Perez',
  'team': 'Red Bull',
  'home_country': 'Mexico',
  'points': 0},
 {'driver': 'Lando Norris',
  'team': 'McLaren',
  'home_country': 'United Kingdom',
  'points': 0},
 {'driver': 'Charles Leclerc',
  'team': 'Ferrari',
  'home_country': 'Monaco',
  'points': 26},
 {'driver': 'Valtteri Bottas',
  'team': 'Ferrari',
  'home_country': 'Spain',
  'points': 8}]
Mark
  • 90,562
  • 7
  • 108
  • 148
0

You can't do assignment (A=B) in a comprehension. You could possibly use the update function. For example:

[driver.update({'points': drivers_with_points[driver["driver"]]}) for driver in standings if driver["driver"] in drivers_with_points.keys()]
NPGuy
  • 11
  • 2
  • [Don't use list comprehensions for side-effects](https://stackoverflow.com/q/5753597/843953) – Pranav Hosangadi Mar 29 '22 at 15:50
  • @PranavHosangadi Agree that this would be bad practice. However, the OP specifically asked how he could achieve his objective (ridiculous as it may be) using a list comprehension. In which case, this answers the question. – DarkKnight Mar 29 '22 at 15:53
  • 2
    This may answer the question, but it's not a *useful* answer to others. The useful answer is, "don't do this". – Mark Mar 29 '22 at 15:57
  • I never said he should, I only said he could. – NPGuy Mar 29 '22 at 16:37