228

I'm new to Python and I have a simple question, say I have a list of items:

['apple','red','apple','red','red','pear']

Whats the simpliest way to add the list items to a dictionary and count how many times the item appears in the list.

So for the list above I would like the output to be:

{'apple': 2, 'red': 3, 'pear': 1}
wjandrea
  • 23,210
  • 7
  • 49
  • 68
Sophie
  • 2,281
  • 2
  • 14
  • 3

8 Answers8

332

in 2.7 and 3.1 there is special Counter dict for this purpose.

>>> from collections import Counter
>>> Counter(['apple','red','apple','red','red','pear'])
Counter({'red': 3, 'apple': 2, 'pear': 1})
SiHa
  • 6,756
  • 12
  • 30
  • 41
Odomontois
  • 15,341
  • 2
  • 35
  • 70
  • 3
    The official line, or rather standing joke, is that Guido has a time machine .. – Muhammad Alkarouri Aug 17 '10 at 00:04
  • 21
    @Glenn Maynard Counter is just an implementation of a **multiset** which is not an uncommon data structure IMO. In fact, C++ has an implementation in the STL called `std::multiset` (also `std::tr1::unordered_multiset`) so Guido is not alone in his opinion of its importance. – awesomo Oct 18 '11 at 03:07
  • 8
    @awesomo: No, it's not comparable to std::multiset. std::multiset allows storing multiple distinct but comparatively equal values, which is what makes it so useful. (For example, you can compare a list of locations by their temperature, and use a multiset to look up all locations at a specific temperature or temperature range, while getting the fast insertions of a set.) Counter merely counts repetitions; distinct values are lost. That's much less useful--it's nothing more than a wrapped dict. I question calling that a multiset at all. – Glenn Maynard Oct 18 '11 at 15:23
  • 1
    @GlennMaynard You're right, I overlooked the additional (extremely useful) features of std::multiset. – awesomo Oct 18 '11 at 16:11
  • 1
    This is the correct Pythonista way of doing it. Efficient. Most of the other solutions listed work, but are not scalable. Exponentially less efficient. Attend MIT OCW "Introduction to Algorithms" to find out why. – imbatman Jan 18 '18 at 10:17
  • 4
    Counting might be a narrow task, but one that is required very often. – Radio Controlled Mar 26 '19 at 08:36
  • In Python 3.8 it is not correct !!! So first check carefully which python version you are running !!! – Xenia Ioannidou Jul 29 '21 at 18:22
  • @XeniaIoannidou can you check again? I've just tried 3.8 and everythink worked as intended https://replit.com/@Odomontois/InternationalWorthlessLinks#main.py – Odomontois Aug 11 '21 at 07:50
287

I like:

counts = dict()
for i in items:
  counts[i] = counts.get(i, 0) + 1

.get allows you to specify a default value if the key does not exist.

mmmdreg
  • 5,670
  • 2
  • 23
  • 18
69

Simply use list property count\

i = ['apple','red','apple','red','red','pear']
d = {x:i.count(x) for x in i}
print d

output :

{'pear': 1, 'apple': 2, 'red': 3}
ネロク
  • 21,268
  • 3
  • 51
  • 67
Ashish Kumar Verma
  • 1,210
  • 12
  • 20
61
>>> L = ['apple','red','apple','red','red','pear']
>>> from collections import defaultdict
>>> d = defaultdict(int)
>>> for i in L:
...   d[i] += 1
>>> d
defaultdict(<type 'int'>, {'pear': 1, 'apple': 2, 'red': 3})
mechanical_meat
  • 155,494
  • 24
  • 217
  • 209
  • @NickT It's more cluttered than itertools.Counter - and I'd be surprised if it was faster... – Shadow Sep 12 '19 at 01:56
29

I always thought that for a task that trivial, I wouldn't want to import anything. But i may be wrong, depending on collections.Counter being faster or not.

items = "Whats the simpliest way to add the list items to a dictionary "

stats = {}
for i in items:
    if i in stats:
        stats[i] += 1
    else:
        stats[i] = 1

# bonus
for i in sorted(stats, key=stats.get):
    print("%d×'%s'" % (stats[i], i))

I think this may be preferable to using count(), because it will only go over the iterable once, whereas count may search the entire thing on every iteration. I used this method to parse many megabytes of statistical data and it always was reasonably fast.

Stefano Palazzo
  • 4,143
  • 2
  • 27
  • 39
  • 2
    Your answer deserves more credit for it's simplicity. I was struggling over this for a while, getting bewildered with the silliness of some of the other users suggesting to import new libraries etc. – ntk4 Sep 23 '16 at 05:56
  • 1
    you could simplify it with a default value like this d[key] = d.get(key, 0) + 1 – merhoo Jan 22 '19 at 03:26
  • The simplicity of this answer is so underrated! Sometimes there is no need to import libraries and over-engineer simple tasks. – Madhavi Jouhari Aug 02 '21 at 11:15
8

Consider collections.Counter (available from python 2.7 onwards). https://docs.python.org/2/library/collections.html#collections.Counter

Pradyot
  • 2,631
  • 7
  • 38
  • 50
7

How about this:

src = [ 'one', 'two', 'three', 'two', 'three', 'three' ]
result_dict = dict( [ (i, src.count(i)) for i in set(src) ] )

This results in

{'one': 1, 'three': 3, 'two': 2}

riviera
  • 413
  • 4
  • 8
5
L = ['apple','red','apple','red','red','pear']
d = {}
[d.__setitem__(item,1+d.get(item,0)) for item in L]
print d 

Gives {'pear': 1, 'apple': 2, 'red': 3}

Nick T
  • 24,120
  • 11
  • 77
  • 117