Anarcho-Chossid
Anarcho-Chossid

Reputation: 2330

Python: dictionary list comprehension for count of number of instances

I have the following:

a = rand(100).round() #for example
count = {}

for i in a:
    count[i] = count.get(i, 0) + 1

# print(a)
print(count)

The last line returns something like {0.0: 52, 1.0: 48}

I would like to do the for loop as dictionary comprehension. But,

count = {i: count.get(i,0)+1 for i in a}

always returns {0.0: 1, 1.0: 1}

What am I doing wrong?

Upvotes: 3

Views: 1462

Answers (3)

Burhan Khalid
Burhan Khalid

Reputation: 174624

Why not use the appropriately named Counter?

from collections import Counter

>>> c = Counter([1,1,1,1,1,1,1,1,1,1,1,1,5,4,3,2,3,4,1,3,13,12,13,2,1,13,4,4,4])
>>> c
Counter({1: 14, 4: 5, 3: 3, 13: 3, 2: 2, 5: 1, 12: 1})

Upvotes: 3

thefourtheye
thefourtheye

Reputation: 239463

I think the comprehension version of yours look like this,

count = {}
count = {i: count.get(i,0)+1 for i in a}

When the comprehension is executed, count refers to the empty dictionary created in the previous line. So count.get(i,0) always returns 0. That is why the result has 1 always. If you didn't defined in the previous line, you will get

NameError: global name 'count' is not defined

Because the count is not defined yet in the program.

Note: You cannot reference the dictionary being constructed in the dictionary comprehension.

So, updating the dictionary will not work in the comprehension. The solution what you actually have now is fine.

Upvotes: 1

6502
6502

Reputation: 114481

The statement

count = {i: count.get(i,0)+1 for i in a}

is composed of two parts:

{i: count.get(i,0)+1 for i in a}

and

count = ...

the first one computes a dictionary and when evaluating it count is just the empty dictionary you defined first and has no relation with the dictionary being constructed by the comprehension expression.

Only at the end of the dictionary construction this is assigned to count (replacing the empty dictionary). During the comprehension evaluation count is empty and remains empty so every get will always return the default value of 0.

There is no way to refer to the object being constructed in a comprehension (e.g a list or a dictionary) in the expressions used inside the comprehension.

Upvotes: 2

Related Questions