Python creating a dictionary of lists

PythonDictionary

Python Problem Overview


I want to create a dictionary whose values are lists. For example:

{
  1: ['1'],
  2: ['1','2'],
  3: ['2']
}

If I do:

d = dict()
a = ['1', '2']
for i in a:
    for j in range(int(i), int(i) + 2): 
        d[j].append(i)

I get a KeyError, because d[...] isn't a list. In this case, I can add the following code after the assignment of a to initialize the dictionary.

for x in range(1, 4):
    d[x] = list()

Is there a better way to do this? Lets say I don't know the keys I am going to need until I am in the second for loop. For example:

class relation:
    scope_list = list()
...
d = dict()
for relation in relation_list:
    for scope_item in relation.scope_list:
        d[scope_item].append(relation)

An alternative would then be replacing

d[scope_item].append(relation)

with

if d.has_key(scope_item):
    d[scope_item].append(relation)
else:
    d[scope_item] = [relation,]
    

What is the best way to handle this? Ideally, appending would "just work". Is there some way to express that I want a dictionary of empty lists, even if I don't know every key when I first create the list?

Python Solutions


Solution 1 - Python

You can use defaultdict:

>>> from collections import defaultdict
>>> d = defaultdict(list)
>>> a = ['1', '2']
>>> for i in a:
...   for j in range(int(i), int(i) + 2):
...     d[j].append(i)
...
>>> d
defaultdict(<type 'list'>, {1: ['1'], 2: ['1', '2'], 3: ['2']})
>>> d.items()
[(1, ['1']), (2, ['1', '2']), (3, ['2'])]

Solution 2 - Python

You can build it with list comprehension like this:

>>> dict((i, range(int(i), int(i) + 2)) for i in ['1', '2'])
{'1': [1, 2], '2': [2, 3]}

And for the second part of your question use defaultdict

>>> from collections import defaultdict
>>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
>>> d = defaultdict(list)
>>> for k, v in s:
        d[k].append(v)

>>> d.items()
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]

Solution 3 - Python

You can use setdefault:

d = dict()
a = ['1', '2']
for i in a:
    for j in range(int(i), int(i) + 2): 
        d.setdefault(j, []).append(i)

print d  # prints {1: ['1'], 2: ['1', '2'], 3: ['2']}

The rather oddly-named setdefault function says "Get the value with this key, or if that key isn't there, add this value and then return it."

As others have rightly pointed out, defaultdict is a better and more modern choice. setdefault is still useful in older versions of Python (prior to 2.5).

Solution 4 - Python

Personally, I just use JSON to convert things to strings and back. Strings I understand.

import json
s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
mydict = {}
hash = json.dumps(s)
mydict[hash] = "whatever"
print mydict
#{'[["yellow", 1], ["blue", 2], ["yellow", 3], ["blue", 4], ["red", 1]]': 'whatever'}

Solution 5 - Python

Your question has already been answered, but IIRC you can replace lines like:

if d.has_key(scope_item):

with:

if scope_item in d:

That is, d references d.keys() in that construction. Sometimes defaultdict isn't the best option (for example, if you want to execute multiple lines of code after the else associated with the above if), and I find the in syntax easier to read.

Solution 6 - Python

easy way is:

a = [1,2]
d = {}
for i in a:
  d[i]=[i, ]

print(d)
{'1': [1, ], '2':[2, ]}
   

Solution 7 - Python

If you create it from a list, you can also use dict comprehension with a list comprehension within it:

dict_of_list_values = {len(k): [name for name in names if len(name) == len(k)] for k in names}

(I used a list of names for this example)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser118662View Question on Stackoverflow
Solution 1 - Pythonmechanical_meatView Answer on Stackoverflow
Solution 2 - PythonNadia AlramliView Answer on Stackoverflow
Solution 3 - PythonRichieHindleView Answer on Stackoverflow
Solution 4 - Pythonjohn ktejikView Answer on Stackoverflow
Solution 5 - PythonspiffymanView Answer on Stackoverflow
Solution 6 - PythonHenning LeeView Answer on Stackoverflow
Solution 7 - PythonMoti ZamirView Answer on Stackoverflow