识别列表列表中具有3个共同点的列表
问题内容:
我有一个清单清单。如果存在具有相同前三个元素的子列表,请将它们合并为一个列表并添加所有第四个元素。
最好用代码和所需的输出来解释该问题。
a_list = [['apple', 50, 60, 7],
['orange', 70, 50, 8],
['apple', 50, 60, 12]]
# output:
# [['apple', 50, 60, 19], ['orange', 70, 50, 8]]
我已经有一个类似问题的代码(前一段时间由Stack
Overflow中的另一个用户提供给我),但是我不完全了解它,因此无法相应地对其进行修改。该代码的作用是检查第0个和第2个元素是否相同,如果相同,则合并子列表,并添加第1个和第3个元素:
import defaultdict
data = [['42x120x1800', 50, '50x90x800', 60],
['42x120x1800', 8, '50x90x800', 10],
['2x10x800', 5, '5x9x80', 6]]
d = defaultdict(lambda :[0, 0])
for sub_list in data:
key = (sub_list[0], sub_list[2])
d[key][0] += sub_list[1]
d[key][1] += sub_list[3]
new_data = [[key[0], val[0], key[1], val[1]] for key, val in d.iteritems()]
# [['2x10x800', 5, '5x9x80', 6], ['42x120x1800', 58, '50x90x800', 70]]
应该如何修改代码以适合我的新问题?如果您也能抽出宝贵的时间对代码进行彻底的解释,我将不胜感激。
问题答案:
您可以使用相同的原理,方法是将前三个元素用作键,并将int
用作默认值工厂defaultdict
(这样您将获得0
初始值):
from collections import defaultdict
a_list = [['apple', 50, 60, 7],
['orange', 70, 50, 8],
['apple', 50, 60, 12]]
d = defaultdict(int)
for sub_list in a_list:
key = tuple(sub_list[:3])
d[key] += sub_list[-1]
new_data = [list(k) + [v] for k, v in d.iteritems()]
如果您使用的是Python 3,则可以简化为:
d = defaultdict(int)
for *key, v in a_list:
d[tuple(key)] += v
new_data = [list(k) + [v] for k, v in d.items()]
因为您可以使用加星标的目标从列表中获取所有“剩余”值,所以每个子列表主要分配给key
,最后一个值分配给v
,从而使循环变得更简单了(并且.iteritems()
dict中没有方法Python
3,因为.items()
已经是一个迭代器)。
所以,我们使用一个defaultdict
使用0
作为默认值,然后从第3个值产生的每个键(作为一个元组,所以你可以使用它作为一个字典的键)总结的最后一个值。
-
因此,对于第一个项目,
['apple', 50, 60, 7]
我们创建一个key('apple', 50, 60)
,在d
其中查找键(该键不存在,但是defaultdict
将int()
用于创建新值0
),然后7
从该第一项中添加。 -
对
('orange', 70, 50)
键和值执行相同的操作8
。 -
对于第3个项目,我们
('apple', 50, 60)
再次获取密钥,并将其添加12
到中已存在的密钥7
中d[('apple', 50, 60)]
。共19个
然后,我们将(键,值)对重新放入列表中,您就完成了。结果是:
>>> new_data
[['apple', 50, 60, 19], ['orange', 70, 50, 8]]
需要对数据进行排序的另一种实现方式是itertools.groupby
:
from itertools import groupby
from operator import itemgetter
a_list = [['apple', 50, 60, 7],
['orange', 70, 50, 8],
['apple', 50, 60, 12]]
newlist = [list(key) + [sum(i[-1] for i in sublists)]
for key, sublists in groupby(sorted(a_list), key=itemgetter(0, 1, 2))]
对于相同的输出。如果您的数据未排序,这会变慢,但是很高兴知道不同的方法。