python dictionary comprehension iterator

2019-08-14 02:14发布

Hey I have a doubt in the following python code i wrote :

#create a list of elements
#use a dictionary to find out the frequency of each element
list = [1,2,6,3,4,5,1,1,3,2,2,5]
list.sort()
dict = {i: list.count(i) for i in list}
print(dict)

In the dictionary compression method, "for i in list" is the sequence supplied to the method right ? So it takes 1,2,3,4.. as the keys. My question is why doesn't it take 1 three times ? Because i've said "for i in list", doesn't it have to take each and every element in the list as a key ?

(I'm new to python so be easy on me !)

2条回答
爷的心禁止访问
2楼-- · 2019-08-14 02:50

My question is why doesn't it take 1 three times ?

That's because dictionary keys are unique. If there is another entry found for the same key, the previous value for that key will be overwritten.

Well, for your issue, if you are only after counting the frequency of each element in your list, then you can use collections.Counter

And please don't use list as variable name. It's a built-in.

>>> lst = [1,2,6,3,4,5,1,1,3,2,2,5]
>>> from collections import Counter
>>> Counter(lst)
Counter({1: 3, 2: 3, 3: 2, 5: 2, 4: 1, 6: 1})
查看更多
老娘就宠你
3楼-- · 2019-08-14 03:02

Yes, your suspicion is correct. 1 will come up 3 times during iteration. However, since dictionaries have unique keys, each time 1 comes up it will replace the previously generated key/value pair with the newly generated key/value pair. This will give the right answer, it's not the most efficient. You could convert the list to a set instead to avoid reprocessing duplicate keys:

dict = {i: list.count(i) for i in set(list)}

However, even this method is horribly inefficient because it does a full pass over the list for each value in the list, i.e. O(n²) total comparisons. You could do this in a single pass over the list, but you wouldn't use a dict comprehension:

xs = [1,2,6,3,4,5,1,1,3,2,2,5]
counts = {}
for x in xs:
  counts[x] = counts.get(x, 0) + 1

The result for counts is: {1: 3, 2: 3, 3: 2, 4: 1, 5: 2, 6: 1}

Edit: I didn't realize there was something in the library to do this for you. You should use Rohit Jain's solution with collections.Counter instead.

查看更多
登录 后发表回答