Python creating a dictionary of lists

Question:

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?

Asked By: user118662

||

Answers:

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).

Answered By: RichieHindle

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])]
Answered By: Nadia Alramli

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'])]
Answered By: mechanical_meat

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.

Answered By: spiffyman

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'}
Answered By: john ktejik

easy way is:

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

print(d)
{'1': [1, ], '2':[2, ]}
Answered By: Henning Lee

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)

Answered By: Moti Zamir

Here the solution is given along with list comprehension.

https://youtu.be/yQTktgP9Wl0

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