Python2按值合并列表

时间:2017-01-23 06:04:39

标签: python list

我有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))]

没有像我预期的那样工作。

有没有办法做到这一点?

2 个答案:

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