我有4个元素的列表,它看起来像:
L = [['grape','green',2, 100], ['grape','purple',3,3], ['apple','red',2, 15], ['apple','greed',3, 10],
['apple','red',4, 4], ['banana','yellow',2, 3]]
我想有一个函数通过第一个元素合并该列表,连接第二个和第三个元素,然后总结最后一个元素以获得输出:
[['grape',['green,purple'],[2,3],103],['banana','yellow',2, 3],['apple',['red','green','red'],[2,3,4],29]
我尝试了以下代码:
[(x,sum(map(itemgetter(3),y))) for x,y in itertools.groupby(L, itemgetter(0))], which can successfully sum up the last element, but
[(x,(map(itemgetter(1),y)),(map(itemgetter(2),y)),sum(map(itemgetter(3),y))) for x,y in itertools.groupby(L, itemgetter(0))]
没有像我预期的那样工作。
有没有办法做到这一点?
答案 0 :(得分:4)
使用itertools.groupby()
您需要两次单独的迭代:
In [20]: [[i[0], j, k, sum(z)] for i, j, k, z in [zip(*g) for _, g in groupby(L, itemgetter(0))]]
Out[20]:
[['grape', ('green', 'purple'), (2, 3), 103],
['apple', ('red', 'greed', 'red'), (2, 3, 4), 29],
['banana', ('yellow',), (2,), 3]]
以下是使用collections.defaultdict
的另一种方式,但不是优化:
In [34]: d = defaultdict(list)
In [35]: for i, j, k, z in L:
d[i].append((j, k, z))
....:
In [36]: [[i, j, k, sum(z)] for i, j, k, z in [[i, *zip(*values)] for i, values in d.items()]]
Out[36]:
[['banana', ('yellow',), (2,), 3],
['apple', ('red', 'greed', 'red'), (2, 3, 4), 29],
['grape', ('green', 'purple'), (2, 3), 103]]
注意列表中的*zip(...)
被称为就地解包,并且仅在python 3.5 +中可用。
答案 1 :(得分:1)
另一种基于groupby
的解决方案,更少纠缠并提供所需的输出:
import operator, itertools
l = [['grape','green',2, 100], ['grape','purple',3,3], ['apple','red',2, 15], ['apple','greed',3, 10],
['apple','red',4, 4], ['banana','yellow',2, 3]]
res = []
for key, group in itertools.groupby(l, operator.itemgetter(0)):
i,j,k,l = [i[0] if len(i) == 1 else list(i) for i in zip(*group)]
res.append([key, j, k, l if type(l) == int else sum(l)])
print(res)
输出:
[['grape', ['green', 'purple'], [2, 3], 103], ['apple', ['red', 'greed', 'red'], [2, 3, 4], 29], ['banana', 'yellow', 2, 3]]