繁体   English   中英

使用嵌套列表解压缩python的值太多了

[英]too many values to unpack python with nested list

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:要解压缩的值太多

我试图理解为什么会发生这种情况,但这两个列表的嵌套结构看起来完全相同。

你在list_b传递时得到ValueError的原因是因为在执行时:

for name, value in matrix:
    ...

Python期望some_list的元素能够被解压缩为两个变量; namevalue 这对list_a是正确的。 list_a有一个元素可以解压缩为两个变量namevalue 但是, list_b有一个元素有两个以上的元素。 这意味着它无法解压缩为两个变量。 因此,提出了例外。

显而易见的解决方案是将list_b重组list_b每个元素组成的列表,每个元素都有两个元素。 要做到这一点的一般方法是使用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)]
>>>  

问题

您需要将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]]

list_b应该是2个项目列表的列表:

list_b = [['name2', 2], ['name4', 4], ['name4', 1], ['name4', 6], ['name2', 6]]

它没有做你认为它正在做的事情。 在第一个列表中,它将两个值分成namevalue 这是有效的,因为列表中的项目数量与for循环中的项目数量完全相同。

对于第二个列表,有10个项目,这比在for循环中解压缩的两个项目更多。

为了实现这一点,您的值需要以两对的形式嵌套。

这可以解决您的问题:

list_b = [['name2', 2], ['name4', 4], [ 'name4', 1], ['name4', 6], ['name2', 6]]

list_b只包含一个元素, ['name2', 2, 'name4', 4, 'name4', 1, 'name4', 6, 'name2', 6] 要在for循环中解压缩list_b ,您需要使用十个变量:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM