How to add or increment a dictionary entry?

Question:

I’m currently re-engaging with Python after a long absence and loving it. However, I find myself coming across a pattern over and over. I keep thinking that there must be a better way to express what I want and that I’m probably doing it the wrong way.

The code that I’m writing is in the following form:

# foo is a dictionary
if foo.has_key(bar):
  foo[bar] += 1
else:
  foo[bar] = 1

I’m writing this a lot in my programs. My first reaction is to push it out to a helper function, but so often the python libraries supply things like this already.

Is there some simple little syntax trick that I’m missing? Or is this the way that it should be done?

Asked By: cursa

||

Answers:

Use a defaultdict:

from collections import defaultdict

foo = defaultdict(int)
foo[bar] += 1

In Python >= 2.7, you also have a separate Counter class for these purposes. For Python 2.5 and 2.6, you can use its backported version.

Answered By: Tamás

For Python >= 2.5 you can do the following:

foo[bar] = 1 if bar not in foo else foo[bar]+1
Answered By: thetaiko

You can also take advantage of the control structure in exception handling. A KeyError exception is thrown by a dictionary when you try to assign a value to a non-existent key:

my_dict = {}
try:
    my_dict['a'] += 1
except KeyError, err:    # in 2.6: `except KeyError as err:`
    my_dict['a'] = 1
Answered By: Santa

The dict‘s get() method takes an optional second parameter that can be used to provide a default value if the requested key is not found:

foo[bar] = foo.get(bar, 0) + 1
Answered By: sth

I did some time comparisons. Pretty much equal. The one-lined .get() command is fastest, though.

Output:

get 0.543551800627
exception 0.587318710994
haskey 0.598421703081

Code:

import timeit
import random

RANDLIST = [random.randint(0, 1000) for i in range(10000)]

def get():
    foo = {}
    for bar in RANDLIST:
        foo[bar] = foo.get(bar, 0) + 1


def exception():
    foo = {}
    for bar in RANDLIST:
        try:
            foo[bar] += 1
        except KeyError:
            foo[bar] = 1


def haskey():
    foo = {}
    for bar in RANDLIST:
        if foo.has_key(bar):
            foo[bar] += 1
        else:
            foo[bar] = 1


def main():
    print 'get', timeit.timeit('get()', 'from __main__ import get', number=100)
    print 'exception', timeit.timeit('exception()', 'from __main__ import exception', number=100)
    print 'haskey', timeit.timeit('haskey()', 'from __main__ import haskey', number=100)


if __name__ == '__main__':
    main()
Answered By: user297250

I don’t know how this was tried, but if you need to append items in dict keys…

indicatorDict = {}
indicatorDict[0] = 'Langford'
indicatorDict[1] = 'Esther'
indicatorDict[3] = 14

Append items to it, be it iteratively or other types:

indicatorDict[0] = np.append(indicatorDict[0],'Auditorium')
indicatorDict[1] = np.append(indicatorDict[1],'Duflo')
indicatorDict[3] = np.append(indicatorDict[3],'November') 

Printing …

{0: array(['Langford', 'Auditorium'], dtype='<U10'),
 1: array(['Esther', 'Duflo'], dtype='<U6'),
 3: array(['14', 'November'], dtype='<U11')}

I avoided 3rd key in Dict to show that if needed keys can be jumped from one step to another… 🙂
Hope it helps!

Answered By: banikr
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.