How to create key or append an element to key?

Question:

I have an empty dictionary. Name: dict_x
It is to have keys of which values are lists.

From a separate iteration, I obtain a key (ex: key_123), and an item (a tuple) to place in the list of dict_x‘s value key_123.

If this key already exists, I want to append this item.
If this key does not exist, I want to create it with an empty list and then append to it or just create it with a tuple in it.

In future when again this key comes up, since it exists, I want the value to be appended again.

My code consists of this:

Get key and value.

See if NOT key exists in dict_x.

and if not create it: dict_x[key] == []

Afterwards: dict_x[key].append(value)

Is this the way to do it? Shall I try to use try/except blocks?

Asked By: Phil

||

Answers:

Use dict.setdefault():

dict.setdefault(key,[]).append(value)

help(dict.setdefault):

    setdefault(...)
        D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D
Answered By: Ashwini Chaudhary

You can use defaultdict in collections.

An example from doc:

s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
d = defaultdict(list)
for k, v in s:
    d[k].append(v)
Answered By: iMom0

You can use a defaultdict for this.

from collections import defaultdict
d = defaultdict(list)
d['key'].append('mykey')

This is slightly more efficient than setdefault since you don’t end up creating new lists that you don’t end up using. Every call to setdefault is going to create a new list, even if the item already exists in the dictionary.

Answered By: Nathan Villaescusa

Here are the various ways to do this so you can compare how it looks and choose what you like. I’ve ordered them in a way that I think is most “pythonic”, and commented the pros and cons that might not be obvious at first glance:

Using collections.defaultdict:

import collections
dict_x = collections.defaultdict(list)

...

dict_x[key].append(value)

Pros: Probably best performance. Cons: Not available in Python 2.4.x.

Using dict().setdefault():

dict_x = {}

...

dict_x.setdefault(key, []).append(value)

Cons: Inefficient creation of unused list()s.

Using try ... except:

dict_x = {}

...

try:
    values = dict_x[key]
except KeyError:
    values = dict_x[key] = []
values.append(value)

Or:

try:
    dict_x[key].append(value)
except KeyError:
    dict_x[key] = [value]
Answered By: antak
dictionary['key'] = dictionary.get('key', []) + list_to_append

TL;DR

The more lengthy and expressive approach seems also to be more performant.

if key in dest:
    dest[key].append(value)
else:
    dest[key] = [value]

Longer answer

I wrote some python lines to check whether the proposed approach is actually the best in term of performance.

d1 = {}
d2 = {}

def add1(key, value, dest):
        dest.setdefault(key, []).append(value)
            
def add2(key, value, dest):
    if key in dest:
        dest[key].append(value)
    else:
        dest[key] = [value]

This results in

%timeit add1('a', 1.1, d1)
  96.2 ns ± 0.0972 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)
%timeit add2('a', 1.1, d2)
  89.1 ns ± 0.111 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)

Tested on my python setup (3.10.4 (main, Apr 2 2022, 09:04:19) [GCC 11.2.0]) executing Jupyter NB.

It’s worth it to point out that opting for the lengthier and more expressive approach can also impact positively on performance in this case.

Answered By: Franc
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.