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?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
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
Method 2
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]
Method 3
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.
Method 4
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)
Method 5
dictionary['key'] = dictionary.get('key', []) + list_to_append
Method 6
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.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0