我试图使用itertools.groupby来帮助我按正面或负面属性对整数列表进行分组,例如:
输入
[1,2,3, -1,-2,-3, 1,2,3, -1,-2,-3]
将返回
[[1,2,3],[-1,-2,-3],[1,2,3],[-1,-2,-3]]
但是如果我:
import itertools
nums = [1,2,3, -1,-2,-3, 1,2,3, -1,-2,-3]
group_list = list(itertools.groupby(nums, key=lambda x: x>=0))
print(group_list)
for k, v in group_list:
print(list(v))
>>>
[]
[-3]
[]
[]
但如果我没有list()
groupby对象,它将正常工作:
nums = [1,2,3, -1,-2,-3, 1,2,3, -1,-2,-3]
group_list = itertools.groupby(nums, key=lambda x: x>=0)
for k, v in group_list:
print(list(v))
>>>
[1, 2, 3]
[-1, -2, -3]
[1, 2, 3]
[-1, -2, -3]
我不明白的是,groupby对象是由一对key和_grouper
对象组成的迭代器,groupby对象的list()
调用不应该使用{{1对象?
即使它确实消耗了,我如何从第二个元素中获得_grouper
?
答案 0 :(得分:3)
每the docs,明确指出推进groupby
对象会导致前一个组无法使用(实际上是空的):
返回的组本身就是一个迭代器,它与
groupby()
共享底层的iterable。由于源是共享的,因此当groupby()
对象前进时,前一个组不再可见。因此,如果以后需要该数据,则应将其存储为列表。
基本上,代替list
- 直接使用list
构造函数,您需要一个listcomp,在推进list
之前将组迭代器转换为groupby
s对象,替换:
group_list = list(itertools.groupby(nums, key=lambda x: x>=0))
使用:
group_list = [(k, list(g)) for k, g in itertools.groupby(nums, key=lambda x: x>=0)]
大多数itertools
模块类型的设计旨在避免隐式存储数据,因为它们旨在与潜在的巨大输入一起使用。如果所有的石斑鱼都存储了输入中所有数据的副本(并且groupby
对象必须确保追溯填充它们),它将变得丑陋,并且可能意外地记忆。通过强制您将值显式存储,根据Python的Zen,您不会无意中无意中存储无限量的数据:
明确比隐含更好。