d = {
'a': [[1, 2, 3], [1, 2, 3]],
'b': [[2, 4, 1], [1, 6, 1]],
}
def add_element(lst):
ad = [sum(i) for i in zip(*lst)]
return ad
def csv_reducer2(dicty):
return {k: list(map(add_element, v)) for k, v in dicty.items()}
csv_reducer2(d)
required output:
{'b': [3, 10, 2], 'a': [2, 4, 6]}
Above is the code I have been trying but it gives an error
zip argument #1 must support iteration
>>> d = {'a': [[1, 2, 3], [1, 2, 3]], 'b': [[2, 4, 1], [1, 6, 1]]}
>>> {k: map(sum, zip(*v)) for k, v in d.items()}
{'a': [2, 4, 6], 'b': [3, 10, 2]}
The following will work on Python 2 or 3:
>>> {k: [a + b for a, b in zip(*v)] for k, v in d.items()}
{'a': [2, 4, 6], 'b': [3, 10, 2]}
The issue with your code is you are mapping add_element to every individual element in v inside your dictionary comprehension. This passes a one-dimensional list to zip in add_element, resulting in your error (since individual integers don't support iteration.
To fix your original code, the only change you need to make is:
return {k: list(map(add_element, v)) for k, v in dicty.items()}
->
return {k: add_element(v) for k, v in dicty.items()}
Because zip(*lst) is trying to transpose multiple rows into columns, but you are only passing it single rows through your original map
Related
Say I have a dictionary comprised of integer keys, and a list of integers corresponding to each key.
myDict = {0:[1,2,3,4], 1:[1,2,3], 2:[3,4,5]}
How do I search the list in key 1 for the integer 4, and if it's not in the list append it so that 1:[1,2,3,4]
Try this:
myDict = {0:[1,2,3,4], 1:[1,2,3], 2:[3,4,5]}
# Only if k exists in 'dict'. We append value for that specific key
def search_append(d, k, v):
if (k in d) and (not v in d[k]):
d[k].append(v)
search_append(myDict, 1, 4)
print(myDict)
{0: [1, 2, 3, 4], 1: [1, 2, 3, 4], 2: [3, 4, 5]}
# if k is not in 'dict' we create a key and append the value
def search_append_2(d, k, v):
if not v in d.get(k, []):
d.setdefault(k, []).append(v)
search_append_2(myDict, 3, 4)
print(myDict)
# {0: [1, 2, 3, 4], 1: [1, 2, 3], 2: [3, 4, 5], 3: [4]}
I would like to merge two dictionaries, but if they have the same key, I would only merge non-duplicate values.
The following code works, but I have a question if it's possible to rewrite this when trying to get a union by using | or (**dict1, **dict2)? When I tried using |, my output would be from this dict_merge({ 'A': [1, 2, 3] }, { 'A': [2, 3, 4] }) to this {'A': [2, 3, 4]}
def dict_merge(dict1, dict2):
for key in dict2.keys():
if key in dict1.keys():
d3 = dict1[key] + dict2[key]
d3 = set(d3)
dict1[key] = list(d3)
else:
dict1[key] = dict2[key]
return dict1
dict_merge({ 'A': [1, 2, 3] }, { 'B': [2, 4, 5, 6]})
Output
{ 'A': [1, 2, 3], 'B': [2, 4, 5, 6] }
Giving your two dictionaries names, let's get the union of their keys.
>>> d1 = { 'A': [1, 2, 3] }
>>> d2 = { 'A': [2, 3, 4] }
>>> d1.keys() | d2.keys()
{'A'}
Assuming the lists are really sets based on your code, we can now iterate over the union of the keys in a dictionary comprehension, and union those two sets and turning them back into a list.
>>> {k: list(set(d1.get(k, [])) | set(d2.get(k, []))) for k in d1.keys() | d2.keys()}
{'A': [1, 2, 3, 4]}
If we incorporate some more interesting dictionaries and repeat the same dictionary comprehension:
>>> d1 = {'A': [1,2,3], 'B': [4,5,6]}
>>> d2 = {'B': [5,6,7,8], 'C': [9,10]}
>>> {k: list(set(d1.get(k, [])) | set(d2.get(k, []))) for k in d1.keys() | d2.keys()}
{'C': [9, 10], 'A': [1, 2, 3], 'B': [4, 5, 6, 7, 8]}
Is that the solution you're wanting?
In [61]: my_dict = {}
...: d1 = {'A': [1, 2, 3], 'C': 123}
...: d2 = {'B': [2, 3, 4], 'A': [1, 2, 3]}
...: for i in set(d1).symmetric_difference(set(d2)):
...: my_dict[i] = d1[i] if i in d1 else d2[i]
...: print(my_dict)
Output :
{'B': [2, 3, 4], 'C': 123}
I have a dictionary (dict_) with lists of integers as values.
I want to make an operation on these list and save the result as a new dictionary.
Below I do an operation on these list, adding 2 if the elements are larger than 5. I use a nested for loop to achieve this. How would I achieve the same using dictionary comprehension?
dict_={'a':[5, 8, 7],
'b':[4, 7, 2],
'c':[2, 2, 4]}
print(dict_)
#Output: {'a': [5, 8, 7], 'b': [4, 7, 2], 'c': [2, 2, 4]}
dict_new = {}
for k, v in dict_.items():
list_temp=[]
for e in v:
if e > 5:
ne=e + 2
list_temp.append(ne)
else:
list_temp.append(e)
dict_new[k] = list_temp
print(dict_new)
# Output: {'a': [5, 8, 7], 'b': [4, 7, 2], 'c': [2, 2, 4]}
this could be your dict-comprehension:
{k: [i if i <= 5 else i + 2 for item in v] for k, v in dict_.items()}
note that you need a list-comprehension for the values as well.
noting that False is basically 0 and True is 1 you could simplify (but maybe making it more obscure?) the list-comprehension:
{k: [i + 2 * (i > 5) for i in v] for k, v in dict_.items()}
You can do this, but as you are working with both dicts and lists, you will want to use a list comprehension also.
my_dict ={'a':[5, 8, 7],
'b':[4, 7, 2],
'c':[2, 2, 4]}
d = {key: [x if x <= 5 else x + 2 for x in value] for key, value in my_dict.items()}
This should solve the above problem and return:
{'a': [5, 10, 9], 'b': [4, 9, 2], 'c': [2, 2, 4]}
for k, v in dict_.items():
dict_new[k] = [e + 2 if e > 5 else e for e in v ]
If I have a nested dictionary in Python, is there any way to restructure it based on keys?
I'm bad at explaining, so I'll give a little example.
d = {'A':{'a':[1,2,3],'b':[3,4,5],'c':[6,7,8]},
'B':{'a':[7,8,9],'b':[4,3,2],'d':[0,0,0]}}
Re-organize like this
newd = {'a':{'A':[1,2,3],'B':[7,8,9]},
'b':{'A':[3,4,5],'B':[4,3,2]},
'c':{'A':[6,7,8]},
'd':{'B':[0,0,0]}}
Given some function with inputs like
def mysteryfunc(olddict,newkeyorder):
????
mysteryfunc(d,[1,0])
Where the [1,0] list passed means to put the dictionaries 2nd level of keys in the first level and the first level in the 2nd level. Obviously the values need to be associated with their unique key values.
Edit:
Looking for an answer that covers the general case, with arbitrary unknown nested dictionary depth.
Input:
d = {'A':{'a':[1,2,3],'b':[3,4,5],'c':[6,7,8]},
'B':{'a':[7,8,9],'b':[4,3,2],'d':[0,0,0]}}
inner_dict={}
for k,v in d.items():
print(k)
for ka,va in v.items():
val_list=[]
if ka not in inner_dict:
val_dict={}
val_dict[k]=va
inner_dict[ka]=val_dict
else:
val_dict=inner_dict[ka]
val_dict[k]=va
inner_dict[ka]=val_dict
Output:
{'a': {'A': [1, 2, 3], 'B': [7, 8, 9]},
'b': {'A': [3, 4, 5], 'B': [4, 3, 2]},
'c': {'A': [6, 7, 8]},
'd': {'B': [0, 0, 0]}}
you can use 2 for loops, one to iterate over each key, value pair and the second for loop to iterate over the nested dict, at each step form the second for loop iteration you can build your desired output:
from collections import defaultdict
new_dict = defaultdict(dict)
for k0, v0 in d.items():
for k1, v1 in v0.items():
new_dict[k1][k0] = v1
print(dict(new_dict))
output:
{'a': {'A': [1, 2, 3], 'B': [7, 8, 9]},
'b': {'A': [3, 4, 5], 'B': [4, 3, 2]},
'c': {'A': [6, 7, 8]},
'd': {'B': [0, 0, 0]}}
You can use recursion with a generator to handle input of arbitrary depth:
def paths(d, c = []):
for a, b in d.items():
yield from ([((c+[a])[::-1], b)] if not isinstance(b, dict) else paths(b, c+[a]))
from collections import defaultdict
def group(d):
_d = defaultdict(list)
for [a, *b], c in d:
_d[a].append([b, c])
return {a:b[-1][-1] if not b[0][0] else group(b) for a, b in _d.items()}
print(group(list(paths(d))))
Output:
{'a': {'A': [1, 2, 3], 'B': [7, 8, 9]}, 'b': {'A': [3, 4, 5], 'B': [4, 3, 2]}, 'c': {'A': [6, 7, 8]}, 'd': {'B': [0, 0, 0]}}
I'd like to do the cartesian product of multiple dicts, based on their keys, and then sum the produced tuples, and return that as a dict. Keys that don't exist in one dict should be ignored (this constraint is ideal, but not necessary; i.e. you may assume all keys exist in all dicts if needed). Below is basically what I'm trying to achieve (example shown with two dicts). Is there a simpler way to do this, and with N dicts?
def doProdSum(inp1, inp2):
prod = defaultdict(lambda: 0)
for key in set(list(inp1.keys())+list(inp2.keys())):
if key not in prod:
prod[key] = []
if key not in inp1 or key not in inp2:
prod[key] = inp1[key] if key in inp1 else inp2[key]
continue
for values in itertools.product(inp1[key], inp2[key]):
prod[key].append(values[0] + values[1])
return prod
x = doProdSum({"a":[0,1,2],"b":[10],"c":[1,2,3,4]}, {"a":[1,1,1],"b":[1,2,3,4,5]})
print(x)
Output (as expected):
{'c': [1, 2, 3, 4], 'b': [11, 12, 13, 14, 15], 'a': [1, 1, 1, 2, 2, 2,
3, 3, 3]}
You can do it like this, by first reorganizing your data by key:
from collections import defaultdict
from itertools import product
def doProdSum(list_of_dicts):
# We reorganize the data by key
lists_by_key = defaultdict(list)
for d in list_of_dicts:
for k, v in d.items():
lists_by_key[k].append(v)
# list_by_key looks like {'a': [[0, 1, 2], [1, 1, 1]], 'b': [[10], [1, 2, 3, 4, 5]],'c': [[1, 2, 3, 4]]}
# Then we generate the output
out = {}
for key, lists in lists_by_key.items():
out[key] = [sum(prod) for prod in product(*lists)]
return out
Example output:
list_of_dicts = [{"a":[0,1,2],"b":[10],"c":[1,2,3,4]}, {"a":[1,1,1],"b":[1,2,3,4,5]}]
doProdSum(list_of_dicts)
# {'a': [1, 1, 1, 2, 2, 2, 3, 3, 3],
# 'b': [11, 12, 13, 14, 15],
# 'c': [1, 2, 3, 4]}