Python Itertools groupby使用lambda函数,将列表的子列表分组在一起(如果它们在索引0和1处具有匹配值)

Python Itertools groupby使用lambda函数,将列表的子列表分组在一起(如果它们在索引0和1处具有匹配值),python,performance,group-by,itertools,Python,Performance,Group By,Itertools,我有这样一个列表: data = [['a', 'b', 2000, 100], ['a', 'b', 4000, 500], ['c', 'd', 500, 8000], ['c', 'd', 60, 8000], ['c', 'd', 70, 1000], ['a', 'd', 2000, 100], ['a', 'd', 1000, 100]] 如果前两个值相同,我想把它们组合在一起。产出将是: data = [(['a', 'b', 2000, 100], ['a', 'b', 400

我有这样一个列表:

data = [['a', 'b', 2000, 100], ['a', 'b', 4000, 500], ['c', 'd', 500, 8000], ['c', 'd', 60, 8000], ['c', 'd', 70, 1000], ['a', 'd', 2000, 100], ['a', 'd', 1000, 100]]
如果前两个值相同,我想把它们组合在一起。产出将是:

data = [(['a', 'b', 2000, 100], ['a', 'b', 4000, 500]), (['c', 'd', 500, 8000], ['c', 'd', 60, 8000], ['c', 'd', 70, 1000]), (['a', 'd', 2000, 100], ['a', 'd', 1000, 100])]
具有相同前两个值的子列表在列表中总是彼此相邻,但它们在我需要分组的数量上有所不同

我试过这个:

from itertools import groupby
data = [['a', 'b', 2000, 100], ['a', 'b', 4000, 500], ['c', 'd', 500, 8000], ['c', 'd', 60, 8000], ['c', 'd', 70, 1000], ['a', 'd', 2000, 100], ['a', 'd', 1000, 100]]
output = [list(group) for key, group in groupby(data, lambda x:x[0])]

new_data = []
for l in output:
    new_output = [tuple(group) for key, group in groupby(l, lambda x:x[1])]
    for grouped_sub in new_output:
        new_data.append(grouped_sub)

print(new_data)
并得到了输出:

[(['a', 'b', 2000, 100], ['a', 'b', 4000, 500]), (['c', 'd', 500, 8000], ['c', 'd', 60, 8000], ['c', 'd', 70, 1000]), (['a', 'd', 2000, 100], ['a', 'd', 1000, 100])]
[(['a', 'b', 2000, 100], ['a', 'b', 4000, 500]), (['c', 'd', 500, 8000], ['c', 'd', 60, 8000], ['c', 'd', 70, 1000]), (['a', 'd', 2000, 100], ['a', 'd', 1000, 100])]

这正是我想要的。但是,我的列表列表是<代码> LeN(data)=1000000 < /代码>,我知道如果我可以完全跳过for循环,并且在某种程度上得到<代码> GROPbB/<代码>代码> LAMBDA < /Cord>,在分组时考虑<代码> x [0 ] < /代码>和<代码> x(1)< /代码>。但是我还不太明白
groupby
中的
lambda
函数是如何工作的

修改键lambda以返回包含两个元素的元组:

groupby(data, lambda x: tuple(x[0:2]))
i、 e.可以在单个循环/列表中完成:

>>> [tuple(group) for key, group in groupby(data, lambda x: tuple(x[0:2]))]
[(['a', 'b', 2000, 100], ['a', 'b', 4000, 500]), 
 (['c', 'd', 500, 8000], ['c', 'd', 60, 8000], ['c', 'd', 70, 1000]), 
 (['a', 'd', 2000, 100], ['a', 'd', 1000, 100])]

修改键lambda以返回包含两个元素的元组:

groupby(data, lambda x: tuple(x[0:2]))
i、 e.可以在单个循环/列表中完成:

>>> [tuple(group) for key, group in groupby(data, lambda x: tuple(x[0:2]))]
[(['a', 'b', 2000, 100], ['a', 'b', 4000, 500]), 
 (['c', 'd', 500, 8000], ['c', 'd', 60, 8000], ['c', 'd', 70, 1000]), 
 (['a', 'd', 2000, 100], ['a', 'd', 1000, 100])]

为什么不直接按前两项分组:

from itertools import groupby

data = [['a', 'b', 2000, 100], ['a', 'b', 4000, 500], ['c', 'd', 500, 8000], ['c', 'd', 60, 8000], ['c', 'd', 70, 1000], ['a', 'd', 2000, 100], ['a', 'd', 1000, 100]]
res = [tuple(g) for k, g in groupby(data, key=lambda x: x[:2])]
print(res)
输出:

[(['a', 'b', 2000, 100], ['a', 'b', 4000, 500]), (['c', 'd', 500, 8000], ['c', 'd', 60, 8000], ['c', 'd', 70, 1000]), (['a', 'd', 2000, 100], ['a', 'd', 1000, 100])]
[(['a', 'b', 2000, 100], ['a', 'b', 4000, 500]), (['c', 'd', 500, 8000], ['c', 'd', 60, 8000], ['c', 'd', 70, 1000]), (['a', 'd', 2000, 100], ['a', 'd', 1000, 100])]

为什么不直接按前两项分组:

from itertools import groupby

data = [['a', 'b', 2000, 100], ['a', 'b', 4000, 500], ['c', 'd', 500, 8000], ['c', 'd', 60, 8000], ['c', 'd', 70, 1000], ['a', 'd', 2000, 100], ['a', 'd', 1000, 100]]
res = [tuple(g) for k, g in groupby(data, key=lambda x: x[:2])]
print(res)
输出:

[(['a', 'b', 2000, 100], ['a', 'b', 4000, 500]), (['c', 'd', 500, 8000], ['c', 'd', 60, 8000], ['c', 'd', 70, 1000]), (['a', 'd', 2000, 100], ['a', 'd', 1000, 100])]
[(['a', 'b', 2000, 100], ['a', 'b', 4000, 500]), (['c', 'd', 500, 8000], ['c', 'd', 60, 8000], ['c', 'd', 70, 1000]), (['a', 'd', 2000, 100], ['a', 'd', 1000, 100])]

@itay我需要保留在
csv
模块中,因为我将在
pandas
中迭代组和列不是一个好的做法。@itay我需要保留在
csv
模块中,因为我将在
pandas
中迭代组和列不是一个好的做法练习。@AnnaNevison,默认情况下,带slice
x[:2]
-
0
的片段被暗示为起始索引。顺便说一句,我的方法不会强制转换到tuple
tuple(…)
twice@AnnaNevison默认情况下,带切片的
x[:2]
-
0
被暗示为起始索引。顺便说一句,我的方法不会对tuple
tuple(…)
twice进行强制转换谢谢!!这是正确的,您和另一个答案同时用相同的东西进行了注释,但我将接受另一个答案,因为它包含完整的代码,您不需要从0开始切片。(还有,你的有5张赞成票,所以如果我接受他的话,他得到的分数几乎和你一样多)。但是我非常感谢你的帮助!谢谢大家!@安纳尼森,你很有公平感和理性主义。我很少在这里看到这种情况。)好的,谢谢你!!这是正确的,您和另一个答案同时用相同的东西进行了注释,但我将接受另一个答案,因为它包含完整的代码,您不需要从0开始切片。(还有,你的有5张赞成票,所以如果我接受他的话,他得到的分数几乎和你一样多)。但是我非常感谢你的帮助!谢谢大家!@安纳尼森,你很有公平感和理性主义。我很少在这里看到这种情况。)好的