list的字典的和列表



我有一个字典列表,字典中的每个值都是一个四元素列表:

my_dict=[
{
'prop1': [1, 2, 3, 4],
'prop2': [1, 1, 0, 0]
},
{
'prop1': [2, 3, 3, 1],
'prop3': [1, 1, 0, 0]
}
]

可不可以不写显式迭代就求和?

我想要得到:

my_dict_sum={
'prop1': [3, 5, 6, 5],
'prop2': [1, 1, 0, 0],
'prop3': [1, 1, 0, 0]
}

UPD:类似这样的工作,但我想知道如何使用mapzipfunctools来做同样的事情,而不编写两层迭代:

my_dict_sum = {}
for val in my_dict:
for key,counts in val.items():
if key in my_dict_sum :
sum_dict[key] = list(map(lambda x,y: x+y, my_dict_sum[key], counts))
else:
my_dict_sum[key] = counts

EDIT:

这是一个没有显式循环的可怕的单行程序。我不知道你为什么想这么做。你这样做。假设您不将理解计算为显式循环,尽管存在单词"for"

from functools import reduce
output = {k: reduce(
lambda a, b:
map(lambda d, e:
d+e, a, b[k] if k in b else [0,0,0,0]
),
dicts, 
[0, 0, 0, 0]
)
for k in reduce(
lambda s, b:
s | set(b.keys()),
dicts, set()
)
}

这是一个带有显式循环的简单版本,我觉得比你的代码清晰得多,所以也许这就足够了。

from collections import defaultdict
dicts = [
{
'prop1': [1, 2, 3, 4],
'prop2': [1, 1, 0, 0]
},
{
'prop1': [2, 3, 3, 1],
'prop3': [1, 1, 0, 0]
}
]
output = defaultdict(lambda: [0, 0, 0, 0])
for d in dicts:
for k, l in d.items():
for i, v in enumerate(l):
output[k][i] += v

注意,只有当所有列表都恰好有四个项目时,它才会起作用。要处理不知道列表中有多少项的情况,可以使用稍微复杂一点的版本:

output = defaultdict(list)
for d in dicts:
for k, l in d.items():
for i, v in enumerate(l):
if i >= len(output[k]):
output[k].append(v)
else:
output[k][i] += v

可以作为使用reducemap以及一堆lambda的一行代码来完成此操作,但这将是一个难以理解的混乱。如果你担心你的代码中有一堆循环,那就把它放在一个函数中,然后调用这个函数。

考虑到这不是要找到最显式的,或更python化的,或最高效的方法,但您只是好奇它是否可以在任何其他替代方法中实现,这里有一个简短的技巧,没有任何提及for循环:

from itertools import chain
d = {}
items_chain = chain.from_iterable(map(lambda d: list(d.items()), my_dicts))
list(map(lambda t, d=d: d.update([t]) if t[0] not in d else 
d.update([(t[0], list(map(sum, zip(d[t[0]], t[1]))))]), items_chain))
print(d)

{'prop1': [3, 5, 6, 5], 'prop2': [1, 1, 0, 0], 'prop3': [1, 1, 0, 0]}

更新:也许更好的方法是使用内置的UserDict类定义自己的字典,如下所示:

from collections import UserDict
class mydict(UserDict):  
def __add__(self, other):
for k, v in other.items():
if k in self.data:
self.data[k] =  list(map(sum, zip_longest(self.data[k], other[k], fillvalue=0)))
else:
self.data[k] = other.data[k]
return self
def __radd__(self, other):
return self if other == 0 else self.__add__(other)

和现在要转换为新的mydict类的输入列表:(如果数据最初创建为mydict而不是dict,则可以跳过此步骤)

new_dict = [mydict(v) for v in my_dict]

现在你唯一需要做的就是求和:

sum(new_dict)
results:
{'prop1': [3, 5, 6, 5], 'prop2': [1, 1, 0, 0], 'prop3': [1, 1, 0, 0]}

以前的解决方案:

你可以这样做:

from itertools import zip_longest
from collections import defaultdict
out = defaultdict(list)
for line in my_dict:
for key, val in line.items():
out[key] = list(map(sum, zip_longest(val, out[key], fillvalue=0)))

和结果:

defaultdict(list,
{'prop1': [3, 5, 6, 5],
'prop2': [1, 1, 0, 0],
'prop3': [1, 1, 0, 0]})

相关内容

  • 没有找到相关文章

最新更新