问题
I've just started learning python few weeks ago. I'm trying to convert this for loop to a list comprehension. The goal is to retrieve all values with USA as a key. Here's my code:
countries = {'Beijing':{'China':51, 'USA':36, 'Russia':22, 'Great Britain':19}, 'London':{'USA':46, 'China':38, 'Great Britain':29, 'Russia':22}, 'Rio':{'USA':35, 'Great Britain':22, 'China':20, 'Germany':13}}
gold_medals = []
for i in countries:
for j in i:
if countries[i]['USA'] not in gold_medals:
gold_medals.append(countries[i]['USA'])
I tried converting it to list comprehension:
gold_medals2 = [countries[i]['USA'] for i in countries for j in i]
I was able to retrieve all the values associated to 'USA' but there are repetitions. I assume it's because I have no if statement to filter the result.
回答1:
You can't do what you're trying to do with an if in a listcomp; listcomps don't bind to the name they're assigned to until they're finished, so there is no gold_medals2 to perform membership testing against.
You can use other tricks for deduping (while preserving order) though, e.g.:
gold_medals2 = list(dict.fromkeys(countries[i]['USA'] for i in countries for j in i))
On modern Python (3.6+) with insertion-ordered dicts, for hashable values, dict.fromkeys quickly produces the unique items from the input in the order each was first observed. list strips off the (garbage) values (all None) and hash table structure so you end up with the unique items with no kruft. If you're on an older Python, you can use collections.OrderedDict instead of dict.
Bonus, it's much faster than what you were doing. Your original solution is a O(n²) solution; using dict.fromkeys keeps it at O(n) (so if you multiply the input size by 10x, you'll only do ~10x more work, not 100x more work).
来源:https://stackoverflow.com/questions/65227647/where-do-i-put-the-if-statement-in-list-comprehension