list_a = [['name1', 4.12]]
list_b = [['name2', 2, 'name4', 4, 'name4', 1, 'name4', 6, 'name2', 6]]
def data_sums(matrix):
sums = defaultdict(int)
for name, value in matrix:
sums[name] += value
result = [[k,v] for k,v in sums.items()]
return result
当我将list_a
传递给data_sums
时,它会返回[['name1', 4.12]]
(对于此特定情况,它无需加总)。
当我将list_b
传递给data_sums
时,会返回错误:
表示名称,矩阵中的值:ValueError:要解压缩的值太多
我试图理解为什么会这样,但两个列表的嵌套结构看起来都是一样的。
答案 0 :(得分:5)
您在传递ValueError
时获得list_b
的原因是因为这样做:
for name, value in matrix:
...
Python期望some_list
中的元素能够被解压缩为两个变量; name
和value
。这适用于list_a
。 list_a
有一个元素可以解压缩到两个变量name
和value
中。但是,list_b
有一个元素具有两个以上的元素。这意味着它无法解压缩为两个变量。因此,提出了例外。
显而易见的解决方案是将list_b
重组为由每个元素组成的列表,每个元素都有两个元素。执行此操作的一般方法是使用itertools库中的grouper
配方:
>>> from itertools import zip_longest
>>>
>>> def grouper(iterable, n, fillvalue=None):
args = [iter(iterable)] * n
return zip_longest(*args, fillvalue=fillvalue)
>>> list_b = [['name2', 2, 'name4', 4, 'name4', 1, 'name4', 6, 'name2', 6]]
>>> list_b = list(grouper(list_b[0], 2))
>>> list_b
[('name2', 2), ('name4', 4), ('name4', 1), ('name4', 6), ('name2', 6)]
>>>
解决此问题的另一种方法是使用列表切片:
,这种方法的可读性较低且不太通用>>> list_b = [['name2', 2, 'name4', 4, 'name4', 1, 'name4', 6, 'name2', 6]]
>>> inner = list_b[0]
>>> list_b = [(a, b) for (a, b) in zip(inner[::2], inner[1::2])]
>>> list_b
[('name2', 2), ('name4', 4), ('name4', 1), ('name4', 6), ('name2', 6)]
>>>
答案 1 :(得分:2)
您需要将list_b
更改为:
list_b = [['name2', 2], ['name4', 4], ['name4', 1], ['name4', 6], ['name2', 6]]
现在:
>>> data_sums(list_b)
[['name2', 8], ['name4', 11]]
因为在这个循环中:
for name, value in matrix:
概念上会发生这种情况:
name, value = ['name2', 2]
name, value = ['name4', 4]
...
这称为解包。
对于list_b
,会发生这种情况:
name, value = 'name2'
会抛出此错误:
ValueError:解压缩的值太多(预期2)
因为右边只有一个值,但Python需要两个值。
你可以从平面列表开始,然后通过开始零和一个拉开每个第二个元素:
flat_list = ['name2', 2, 'name4', 4, 'name4', 1, 'name4', 6, 'name2', 6]
sums = defaultdict(int)
for name, value in zip(flat_list[::2], flat_list[1::2]):
sums[name] += value
result = [[k,v] for k,v in sums.items()]
结果是:
[['name2', 8], ['name4', 11]]
答案 2 :(得分:1)
list_b
应该是2个项目列表的列表:
list_b = [['name2', 2], ['name4', 4], ['name4', 1], ['name4', 6], ['name2', 6]]
答案 3 :(得分:1)
它没有做你认为它正在做的事情。在第一个列表中,它将两个值分成name
和value
。这样做是因为您的列表中的项目数量与for循环中的项目数量完全相同。
对于第二个列表,有10个项目,这比你在for循环中解包的两个项目要多。
为了使其正常工作,您的值需要以两对的形式嵌套。
这可以解决您的问题:
list_b = [['name2', 2], ['name4', 4], [ 'name4', 1], ['name4', 6], ['name2', 6]]
答案 4 :(得分:1)
list_b
只包含一个元素['name2', 2, 'name4', 4, 'name4', 1, 'name4', 6, 'name2', 6]
。要在list_b
循环中解包for
,您需要使用十个变量:
for name1, val, name2, val2, name3, val3, name4, val4, name5, val5 in list_b:
pass
由于上面的内容很长而且是unpythonic,你可以展平list_b
,然后重新组合:
from collections import defaultdict
def data_sums(matrix):
sums = defaultdict(int)
for name, value in matrix:
sums[name] += value
result = [[k,v] for k,v in sums.items()]
return result
list_b = [['name2', 2, 'name4', 4, 'name4', 1, 'name4', 6, 'name2', 6]]
list_b = [i for b in list_b for i in b]
final_b = [list_b[i:i+2] for i in range(0, len(list_b), 2)]
print(data_sums(final_b))
输出:
[['name4', 11], ['name2', 8]]