嵌套列表根据第一个值组合值

nested lists combine values according to first value

list = [ ['a',14,2], ['b',10,1], ['a',3,12], ['r',5,5], ['r',6,13] ]
result = data_sum(list)

def data_sum(list):
  for set in list:
    current_index = list.index(set)
    string  = set[0]
    for item in list:
      second_index = list.index(each)
      if string == item[0] and current_index != second_index:
        set[0] = item[0]
        set[1] += item[1]
        set[2] += item[2]
        del each

  return list

我的结果应该是

[ ['a',17,14], ['b',10,1], ['r',11,18] ]

如果嵌套列表相同,则根据第一个字符串聚合。

我认为我不能在这里使用set[],因为它不会根据嵌套列表本身内部的元素求和。

  1. 我不确定我是否正确使用 list.index
  2. 到目前为止,输出与原始列表完全相同

首先,listsetstring已经是内置函数,所以不建议使用这些名称。我还认为您使问题稍微复杂化了,因为您需要做的就是将字母组合在一起,然后对值进行一些求和。

为了让这个问题对您来说更简单,您需要以某种方式对每个列表的第一个值进行分组,然后对后面的值求和。一种可能的方法是用 collections.defaultdict 对第一个值进行分组,然后对相应的值求和:

from collections import defaultdict

lsts = [['a',14,2], ['b',10,1], ['a',3,12], ['r',5,5], ['r',6,13]]

groups = defaultdict(list)
for letter, first, second in lsts:
    groups[letter].append([first, second])
# defaultdict(<class 'list'>, {'a': [[14, 2], [3, 12]], 'b': [[10, 1]], 'r': [[5, 5], [6, 13]]})

result = []
for key, value in groups.items():
    sums = [sum(x) for x in zip(*value)]
    result.append([key] + sums)

print(result)

哪些输出:

[['a', 17, 14], ['b', 10, 1], ['r', 11, 18]]

结果列表也可以用这个列表理解来写:

result = [[[key] + [sum(x) for x in zip(*value)]] for key, value in groups.items()]

另一种方法是使用 itertools.groupby:

from itertools import groupby
from operator import itemgetter

grouped = [list(g) for _, g in groupby(sorted(lsts), key = itemgetter(0))]
# [[['a', 3, 12], ['a', 14, 2]], [['b', 10, 1]], [['r', 5, 5], ['r', 6, 13]]]

result = []
for group in grouped:
    numbers = [x[1:] for x in group]
    sums = [sum(x) for x in zip(*numbers)]
    result.append([[group[0][0]] + sums])
print(result)

这也输出:

[['a', 17, 14], ['b', 10, 1], ['r', 11, 18]]

注:第二种方法也可以写成大列表推导式:

result = [[[group[0][0]] + [sum(x) for x in zip(*[x[1:] for x in group])]] for group in [list(g) for _, g in groupby(sorted(lsts), key = itemgetter(0))]]

但这很难看且不可读,不应该使用。