Reputation: 2741
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?
Upvotes: 248
Views: 626512
Reputation: 1
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)
Upvotes: 0
Reputation: 281835
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).
Upvotes: 42
Reputation: 169494
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'])]
Upvotes: 316
Reputation: 584
easy way is:
a = [1,2]
d = {}
for i in a:
d[i]=[i, ]
print(d)
{'1': [1, ], '2':[2, ]}
Upvotes: 2
Reputation: 6614
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'}
Upvotes: 3
Reputation: 624
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.
Upvotes: 2
Reputation: 115011
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])]
Upvotes: 61