How to iterate through dictionary with lists as values - python

Suppose I have the following dictionary:
x = {'a': [1,2,3], 'b': [4,5,6], 'c':[5,6,7]}
I need to convert this into three dictionaries that look like:
{'a':1,'b':4,'c':5}
{'a':2,'b':5,'c':6}
{'a':3,'b':7,'c':7}
Essentially three dictionaries that have the same keys and values that correspond to the same index in each value.
I can do this iteratively but I was wondering if there was a move concise and efficient way of doing this without having a nested for loop.

Assuming you know a key (e.g. a) and you know the lists are all the same length..
[ dict((k,v[i]) for k,v in x.items()) for i in range(len(x['a'])) ]

You can create a list of values for each dictionary, then iterate to get a list of dictionaries:
x = {'a': [1,2,3], 'b': [4,5,6], 'c':[5,6,7]}
myValues = list(zip(*x.values()))
myList = [dict(zip(x.keys(), item)) for item in myValues]
print(myList)
[{'a': 1, 'b': 4, 'c': 5}, {'a': 2, 'b': 5, 'c': 6}, {'a': 3, 'b': 6, 'c': 7}]

Related

Unpack list of dictionaries in Python

Question
According to this answer, in Python 3.5 or greater, it is possible to merge two dictionaries x and y by unpacking them:
z = {**x, **y}
Is it possible to unpack a variadic list of dictionaries? Something like
def merge(*dicts):
return {***dicts} # this fails, of course. What should I use here?
For instance, I would expect that
list_of_dicts = [{'a': 1, 'b': 2}, {'c': 3}, {'d': 4}]
{***list_of_dicts} == {'a': 1, 'b': 2, 'c': 3, 'd': 4}
Note that this question is not about how to merge lists of dictionaries since the link above provides an answer to this. The question here is: is it possible, and how, to unpack lists of dictionaries?
Edit
As stated in the comments, this question is very similar to this one. However, unpacking a list of dictionaries is different from simply merging them. Supposing that there was an operator *** designed to unpack lists of dictionaries, and given
def print_values(a, b, c, d):
print('a =', a)
print('b =', b)
print('c =', c)
print('d =', d)
list_of_dicts = [{'a': 1, 'b': 2}, {'c': 3}, {'d': 4}]
it would be possible to write
print_values(***list_of_dicts)
instead of
print_values(**merge(list_of_dicts))
Another solution is using collections.ChainMap
from collections import ChainMap
dict(ChainMap(*list_of_dicts[::-1]))
Out[88]: {'a': 1, 'b': 2, 'c': 3, 'd': 4}
You could just iterate over the list and use update:
lst = [{'a': 1, 'b': 2}, {'c': 3}, {'d': 4}]
dct = {}
for item in lst:
dct.update(item)
print(dct)
# {'a': 1, 'b': 2, 'c': 3, 'd': 4}
There's no syntax for that, but you can use itertools.chain to concatenate the key/value tuples from each dict into a single stream that dict can consume.
from itertools import chain
def merge(*dicts):
return dict(chain.from_iterable(d.items() for d in dicts))
You can also unpack a list created by a list comprehension as well:
def merge(*dicts):
return dict(*[d.items() for d in dicts])
To merge multiple dictionaries you can use the function reduce:
from functools import reduce
lst = [{'a': 1, 'b': 2}, {'c': 3}, {'d': 4}]
reduce(lambda x, y: dict(**x, **y), lst)
# {'a': 1, 'b': 2, 'c': 3, 'd': 4}
You could use list comprehension and put this iterable object as an argument to dict
def merge(*dicts):
lst = [*[d.items() for d in dicts]]
return dict(lst)
You can just use a list comprehension to iterate over all the dicts in the list and then iterate over each if those dicts' items and finally convert them to dict
>>> lst = [{'a':1}, {'b':2}, {'c':1}, {'d':2}]
>>> dict(kv for d in lst for kv in d.items())
{'a': 1, 'b': 2, 'c': 1, 'd': 2}
You can use reduce to merge two dicts at a time using dict.update
>>> from functools import reduce
>>> lst = [{'a':1}, {'b':2}, {'c':1}, {'d':2}]
>>> reduce(lambda d1, d2: d1.update(d2) or d1, lst, {})
{'a': 1, 'b': 2, 'c': 1, 'd': 2}
When you *dicts its put in as a tuple, you can pull the list out with d[0], then use this comprehension for nonuniform keys
list_of_dicts = [{'a': 1, 'b': 2}, {'c': 3}, {'d': 4}]
def merge(*dicts):
return dict( j for i in dicts[0] for j in i.items())
print(merge(list_of_dicts))
{'a': 1, 'b': 2, 'c': 3, 'd': 4}
[Program finished]

Convert list of dictionaries to: List of dictionaries whose values are lists of one

Given a list of dictionaries, e.g.,
[{'a': 1, 'b': 2}, {'c': 3, 'd': 4}]
... I would like to move each value in each dictionary into a list:
[{'a': [1], 'b': [2]}, {'c': [3], 'd': [4]}]
in a one-liner if practical.
Given a dict list l of dicts:
[{k:[d[k]] for k in d} for d in l]

Creating a list of dictionaries in python

I have a following data set that I read in from a text file:
all_examples= ['A,1,1', 'B,2,1', 'C,4,4', 'D,4,5']
I need to create a list of dictionary as follows:
lst = [
{"A":1, "B":2, "C":4, "D":4 },
{"A":1, "B":1, "C":4, "D":5 }
]
I tried using an generator function but it was hard to create a list as such.
attributes = 'A,B,C'
def get_examples():
for value in examples:
yield dict(zip(attributes, value.strip().replace(" ", "").split(',')))
A one liner, just for fun:
all_examples = ['A,1,1', 'B,2,1', 'C,4,4', 'D,4,5']
map(dict, zip(*[[(s[0], int(x)) for x in s.split(',')[1:]] for s in all_examples]))
Produces:
[{'A': 1, 'C': 4, 'B': 2, 'D': 4},
{'A': 1, 'C': 4, 'B': 1, 'D': 5}]
As a bonus, this will work for longer sequences too:
all_examples = ['A,1,1,1', 'B,2,1,2', 'C,4,4,3', 'D,4,5,6']
Output:
[{'A': 1, 'C': 4, 'B': 2, 'D': 4},
{'A': 1, 'C': 4, 'B': 1, 'D': 5},
{'A': 1, 'C': 3, 'B': 2, 'D': 6}]
Explanation:
map(dict, zip(*[[(s[0], int(x)) for x in s.split(',')[1:]] for s in all_examples]))
[... for s in all_examples] For each element in your list:
s.split(',')[1:] Split it by commas, then take each element after the first
(...) for x in and turn it into a list of tuples
s[0], int(x) of the first letter, with that element converted to integer
zip(*[...]) now transpose your lists of tuples
map(dict, ...) and turn each one into a dictionary!
Also just for fun, but with a focus on understandability:
all_examples = ['A,1,1', 'B,2,1', 'C,4,4', 'D,4,5']
ll = [ x.split(",") for x in all_examples ]
ld = list()
for col in range(1, len(ll[0])):
ld.append({ l[0] : int(l[col]) for l in ll })
print ld
will print
[{'A': 1, 'C': 4, 'B': 2, 'D': 4}, {'A': 1, 'C': 4, 'B': 1, 'D': 5}]
Works as long as the input is csv with integers and lines are same length.
Dissection: I will use the teminology "thing" for A, B and C and "measurement" for the "columns" in the data, i.e. those values in the same "csv-column" of the inut data.
Get the string input data into a list for each line: A,1,1 -> ["A","1","1"]
ll = [ x.split(",") for x in all_examples ]
The result is supposed to be a list of dicts, so let's initialize one:
ld = list()
For each measurement (assuming that all lines have the same number of columns):
for col in range(1, len(ll[0])):
Take the thing l[0], e.g. "A", from the line and assign the numeric value int(), e.g. 1, of the measurement in the respective column l[col], e.g. "1", to the thing. Then use a dictionary comprehension to combine it into the next line of the desired result. Finally append() the dict to the result list ld.
ld.append({ l[0] : int(l[col]) for l in ll })
View unfoamtted. Use print json.dumps(ld, indent=4) for more convenient display:
print ld
Hope this helps. Find more on dict comprehensions e.g. here (Python3 version of this great book).
You actually have a list of strings, and you'd like to have a list of paired dictionaries generated from the same key in the tuple triplets of each string.
To keep this relatively simple, I'll use a for loop instead of a complicated dictionary comprehension structure.
my_dictionary_list = list()
d1 = dict()
d2 = dict()
for triplet_str in all_examples:
key, val1, val2 = triplet_str.split(',')
d1[key] = val1
d2[key] = val2
my_dictionary_list.append(d1)
my_dictionary_list.append(d2)
>>> my_dictionary_list
my_dictionary_list
[{'A': '1', 'B': '2', 'C': '4', 'D': '4'},
{'A': '1', 'B': '1', 'C': '4', 'D': '5'}]
Your question should be "How to crate list of dictionaries?". Here's something you would like to consider.
>>> dict={}
>>> dict2={}
>>> new_list = []
>>> all_examples=['A,1,1', 'B,2,1', 'C,4,4', 'D,4,5']
>>> for k in all_examples:
... ele=k.split(",")
... dict[str(ele[0])]=ele[1]
... dict[str(ele[0])]=ele[2]
... new_list.append(dict)
... new_list.append(dict2)
>>> dict
{'A': '1', 'C': '4', 'B': '2', 'D': '4'}
>>> dict2
{'A': '1', 'C': '4', 'B': '1', 'D': '5'}

Convert list of lists to list of dictionaries

I want to convert a list of lists to a list of dictionaries. I have a way to do it but I suspect there's a better way:
t = [[1,2,3], [4,5,6]]
keys = ['a', 'b', 'c']
[{keys[0]:l[0], keys[1]:l[1], keys[2]:l[2]} for l in t]
with output
[{'a': 1, 'c': 3, 'b': 2}, {'a': 4, 'c': 6, 'b': 5}]
This could be done with a loop, but I bet there's a function to do it even easier. From this answer I'm guessing there's a way to do it with the map command, but I'm not quite sure how.
You can use list comprehension with the dict() constructor and zip:
[dict(zip(keys, l)) for l in t ]
Demo
>>> d = [dict(zip(keys, l)) for l in t ]
>>>
>>> d
[{'a': 1, 'c': 3, 'b': 2}, {'a': 4, 'c': 6, 'b': 5}]
>>>
It can also be solved with a dictionary comprehension, this way:
>>> [{k:v for k,v in zip(keys, l)} for l in t]
[{'c': 3, 'b': 2, 'a': 1}, {'c': 6, 'b': 5, 'a': 4}]

dictionary merging for certain keys

So I want to try and merge only certain keys from one dictionary to another so doing
a = {'a':2, 'b':3, 'c':5}
b = {'d':2, 'e':4}
a.update(b)
>>> a
{'a': 2, 'c': 5, 'b': 3, 'e': 4, 'd': 2} # returns a merge of all keys
However say you only wanted the key and value pair 'd':2 and not all of the elements within the dictionary how would this be possible so you get:
{'a': 2, 'c': 5, 'b': 3, 'd': 2}
If you know you want to update a with b['d'], use this:
a['d'] = b['d']
I don't know if I got what you're asking. Anyway, if you want to update just some keys on a dictionary with keys from another, you can do:
a['d'] = b['d']
or, if you want to update multiple keys:
for to_update in keys_to_update: # keys_to_update is a list
a[to_update] = b[to_update]
You may use following snippet:
a = {'a':2, 'b':3, 'c':5}
b = {'d':2, 'e':4}
desiredKeys = ('d',)
for key, val in b.items():
if key in desiredKeys:
a[key] = b[key]
print( a )
Sample above will output:
{'d': 2, 'b': 3, 'c': 5, 'a': 2}

Categories

Resources