Accumulating values in dictionary

T

Thomas Bellman

Zack said:
There's nothing wrong (that I know of) by doing it as I have up there,
but is there a simpler, easier way? Looking forward to hearing about
how much of a n00b I am. Thanks in advance!

You want the defaultdict type:

import collections
d = collections.defaultdict(lambda: 0)
for person in People:
fav_food = person.fav_food
d[fav_food] += 1

New in Python 2.5, so if you require older Python versions, you
can't use that. Note also that this can become slow if most keys
are unique; the function given to defaultdict will be called the
first time a key is mentioned, and if the keys are mostly unique,
that will be the majority of the times, and calling a pure Python
function is fairly slow in CPython. (It probably won't matter
unless you have many thousands of unique keys, though.)
 
T

Thomas Bellman

Arnaud Delobelle said:
from collections import defaultdict
d = defaultdict(int) # That means the default value will be 0
for person in people:
d[person.fav_food] += 1

Ah! I didn't think of using int as the factory function. If you
use this, then I believe the warning I gave about performance
does not apply; my understanding is that calling built-in functions
(like the int constructor) is fast.
 
Z

Zack

Given a bunch of objects that all have a certain property, I'd like to
accumulate the totals of how many of the objects property is a certain
value. Here's a more intelligible example:

Users all have one favorite food. Let's create a dictionary of
favorite foods as the keys and how many people have that food as their
favorite as the value.

d = {}
for person in People:
fav_food = person.fav_food
if d.has_key(fav_food):
d[fav_food] = d[fav_food] + 1
else:
d[fav_food] = 1

d ends up being something like: {'pie': 400, 'pizza': 200, 'burgers':
100} if 400 people like pie, 200 like pizza and 100 like burgers.

There's nothing wrong (that I know of) by doing it as I have up there,
but is there a simpler, easier way? Looking forward to hearing about
how much of a n00b I am. Thanks in advance!
 
Z

Zack

Given a bunch of objects that all have a certain property, I'd like to
accumulate the totals of how many of the objects property is a certain
value. Here's a more intelligible example:

Users all have one favorite food. Let's create a dictionary of
favorite foods as the keys and how many people have that food as their
favorite as the value.

d = {}
for person in People:
fav_food = person.fav_food
if d.has_key(fav_food):
d[fav_food] = d[fav_food] + 1
else:
d[fav_food] = 1

d ends up being something like: {'pie': 400, 'pizza': 200, 'burgers':
100} if 400 people like pie, 200 like pizza and 100 like burgers.

There's nothing wrong (that I know of) by doing it as I have up there,
but is there a simpler, easier way? Looking forward to hearing about
how much of a n00b I am. Thanks in advance!

Er. OK so I realize now that I could have just done this:

d = {}
for person in people:
fav_food = person.fav_food
d[fav_food] = d.get(fav_food, 0) + 1
 
A

Arnaud Delobelle

Zack said:
Given a bunch of objects that all have a certain property, I'd like to
accumulate the totals of how many of the objects property is a certain
value. Here's a more intelligible example:

Users all have one favorite food. Let's create a dictionary of
favorite foods as the keys and how many people have that food as their
favorite as the value.

d = {}
for person in People:
fav_food = person.fav_food
if d.has_key(fav_food):
d[fav_food] = d[fav_food] + 1
else:
d[fav_food] = 1

This is fine. If I wrote this, I'd write it like this:

d = {}
for person in people:
fav_food = person.fav_food
if fav_food in d:
d[fav_food] += 1
else:
d[fav_food] = 1

You can use d.get() instead:

d = {}
for person in people:
fav_food = person.fav_food
d[fav_food] = d.get(fav_food, 0) + 1

Or you can use a defaultdict:

from collections import defaultdict
d = defaultdict(int) # That means the default value will be 0
for person in people:
d[person.fav_food] += 1

HTH
 
Z

Zack

Arnaud Delobelle said:
from collections import defaultdict
d = defaultdict(int) # That means the default value will be 0
for person in people:
d[person.fav_food] += 1

Ah! I didn't think of using int as the factory function. If you
use this, then I believe the warning I gave about performance
does not apply; my understanding is that calling built-in functions
(like the int constructor) is fast.

Arnaud, that is so badass re: int
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,160
Latest member
CollinStri
Top