问题
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 dict
s, 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