Python Creating a Dictionary of Lists

Python creating a dictionary of lists

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'])]

Python - dictionary of lists

You need to use curly rather than square brackets, but otherwise this is probably as good as it gets:

list1 = ['a', 'b', 'c']
list2 = [1, 2, 3, 4]
my_dict = {'list1': list1, 'list2': list2}

Create a dictionary from multiple lists, one list as key, other as value

Use the zip() function to combine a list of keys with corresponding values, then pass the resulting iterator of (key, value) combinations to dict():

data = {"rows": [dict(zip(key_list, row)) for row in val_list]}

This works because zip(iter1, iter2) pairs up each element from iter1 with those of iter2, and the dict() constructor accepts an iterator of 2-value tuples:

Otherwise, the positional argument must be an iterable object. Each item in the iterable must itself be an iterable with exactly two objects. The first object of each item becomes a key in the new dictionary, and the second object the corresponding value.

In my example above I used a list comprehension to generate the whole output list in a single expression:

>>> key_list = ['key1', 'key2', 'key3']
>>> val_list = [['v0_1', 'v0_2', 'v0_3'], ['v1_1', 'v1_2', 'v1_3'], ['v2_1', 'v2_2', 'v2_3']]
>>> {"rows": [dict(zip(key_list, row)) for row in val_list]}
{'rows': [{'key1': 'v0_1', 'key2': 'v0_2', 'key3': 'v0_3'}, {'key1': 'v1_1', 'key2': 'v1_2', 'key3': 'v1_3'}, {'key1': 'v2_1', 'key2': 'v2_2', 'key3': 'v2_3'}]}
>>> from pprint import pp
>>> pp({"rows": [dict(zip(key_list, row)) for row in val_list]})
{'rows': [{'key1': 'v0_1', 'key2': 'v0_2', 'key3': 'v0_3'},
{'key1': 'v1_1', 'key2': 'v1_2', 'key3': 'v1_3'},
{'key1': 'v2_1', 'key2': 'v2_2', 'key3': 'v2_3'}]}

dict.fromkeys() is the wrong tool here as it reuses the second argument for each of the keys.

Create a dictionary with comprehension

Use a dict comprehension (Python 2.7 and later):

{key: value for (key, value) in iterable}

Alternatively for simpler cases or earlier version of Python, use the dict constructor, e.g.:

pairs = [('a', 1), ('b', 2)]
dict(pairs) #=> {'a': 1, 'b': 2}
dict([(k, v+1) for k, v in pairs]) #=> {'a': 2, 'b': 3}

Given separate arrays of keys and values, use the dict constructor with zip:

keys = ['a', 'b']
values = [1, 2]
dict(zip(keys, values)) #=> {'a': 1, 'b': 2}
2) "zip'ped" from two separate iterables of keys/vals
dict(zip(list_of_keys, list_of_values))

How can I make a dictionary (dict) from separate lists of keys and values?

Like this:

keys = ['a', 'b', 'c']
values = [1, 2, 3]
dictionary = dict(zip(keys, values))
print(dictionary) # {'a': 1, 'b': 2, 'c': 3}

Voila :-) The pairwise dict constructor and zip function are awesomely useful.

Building a dictionary with lists as values using list comprehension

Create a list of list of the values, with the first element of each sublist being the key which is [n] +, then use that to create a dictionary.

m = [[n] + [i[1] for i in [(x%3,x) for x in range(10)]if i[0] == n] for n in range(3)]

dictt = {i[0]:i[1:] for i in m}
print(dictt)

>>> {0: [0, 3, 6, 9], 1: [1, 4, 7], 2: [2, 5, 8]}

All on one line

dictt = {i[0]:i[1:] for i in [[n] + [i[1] for i in [(x%3,x) for x in range(10)]if i[0] == n] for n in range(3)]}

Python idiom for creating dict of dict of list

It depends on what you are trying to achieve; how many keys should be added to the inner dict?

The simplest way is to just create new dict literals for the inner dict:

outerdict = {}
outerdict[name] = {type_: [v1, v2, v3]}

or you could use dict.setdefault() to materialize the inner dict as needed:

outerdict.setdefault(name, {})[type_] = [v1, v2, v3]

or you could use collections.defaultdict() to have it handle new values for you:

from collections import defaultdict

outerdict = defaultdict(dict)
outerdict[name][type_] = [v1, v2, v3]

When parsing a file line by line, I'd use the latter, albeit a little simplified:

from collections import defaultdict

outerdict = defaultdict(dict)
with open(filename) as infh:
for line in infh:
name, _, type_, *values = line.split()
outerdict[name][type_] = [int(i) for i in values]

This uses Python 3 syntax to capture the remaining whitespace-delimited values on the line past the first 3 into values.

The Python 2 version would be:

with open(filename) as infh:
for line in infh:
name, _, type_, values = line.split(None, 3)
outerdict[name][type_] = map(int, values.split())

where I limited the whitespace split to just 3 splits (giving you 4 values), then splitting the values string separately.

To have the inner-most list accumulate all values for repeated (name, type_) key combinations, you'll need to use a slightly more complex defaultdict setup; one that produces an inner defaultdict() set to produce list values:

outerdict = defaultdict(lambda: defaultdict(list))
with open(filename) as infh:
for line in infh:
name, _, type_, values = line.split(None, 3)
outerdict[name][type_].extend(map(int, values.split()))

For the file you actually posted, I'd use a different approach altogether:

import csv
from itertools import islice

outerdict = defaultdict(lambda: defaultdict(list))

with open('ImmgenCons_all_celltypes_MicroarrayExp.csv', 'rb') as infh:
reader = csv.reader(infh, skipinitialspace=True)
# first row contains metadata we need
celltypes = next(reader, [])[3:]

# next two rows can be skipped
next(islice(infh, 2, 2), None)

for row in reader:
name = row[1]
for celltype, value in zip(celltypes, row[3:]):
outerdict[name][celltype].append(float(value))

Creating a dictionary with list of lists in Python

Try using a slice:

inlinkDict[docid] = adoc[1:]

This will give you an empty list instead of a 0 for the case where only the key value is on the line. To get a 0 instead, use an or (which always returns one of the operands):

inlinkDict[docid] = adoc[1:] or 0

Easier way with a dict comprehension:

>>> with open('/tmp/spam.txt') as f:
... data = [line.split() for line in f]
...
>>> {d[0]: d[1:] for d in data}
{'A': ['B', 'C', 'D'], 'C': ['A', 'B', 'D'], 'B': ['E', 'F'], 'D': []}
>>> {d[0]: ' '.join(d[1:]) if d[1:] else 0 for d in data}
{'A': 'B C D', 'C': 'A B D', 'B': 'E F', 'D': 0}

Note: dict keys must be unique, so if you have, say, two lines beginning with 'C' the first one will be over-written.



Related Topics



Leave a reply



Submit