python 2 奇怪的列表理解行为
python 2 strange list comprehension behaviour
我环顾列表理解,发现了一些奇怪的东西。
代码:
a = ['a', 'a', 'a', 'b', 'd', 'd', 'c', 'c', 'c']
print [(len(list(g)), k) if len(list(g)) > 1 else k for k, g in groupby(a)]
结果:
[(0, 'a'), 'b', (0, 'd'), (0, 'c')]
但我想看:
[(3, 'a'), 'b', (2, 'd'), (3, 'c')]
这种行为的原因是什么?
当您在 itertools._grouper
对象上调用 list()
时,您会耗尽该对象。由于您执行了两次,因此第二个实例的长度为 0。
第一个:
if len(list(g))
现在已经筋疲力尽了。那么:
(len(list(g)), k))
它的长度为 0。
您可以在 list
理解中嵌套一个 generator/comprehension 来耗尽对象并在处理之前保存相关数据:
>>> [(y,x) if y>1 else x for x,y in ((k, len(list(g))) for k, g in groupby(a))]
[(3, 'a'), 'b', (2, 'd'), (3, 'c')]
您需要确保 g
的元素只被消耗一次:
>>> print [(len(list(g)), k) if len(list(g)) > 1 else k for k, g in ((k, list(g)) for k, g in groupby(a))]
[(3, 'a'), 'b', (2, 'd'), (3, 'c')]
此代码还将遍历 k, g in groupby(a)
,但会将 g
转换为列表对象。然后,其余代码可以根据需要多次访问 g
(以检查长度),而无需使用结果。
在进行此更改之前,g
是一个 itertools._grouper
对象,这意味着您只能迭代 g
一次。之后它将为空,您将无法再次对其进行迭代。这就是您在结果中看到长度为 0 的原因。
我环顾列表理解,发现了一些奇怪的东西。 代码:
a = ['a', 'a', 'a', 'b', 'd', 'd', 'c', 'c', 'c']
print [(len(list(g)), k) if len(list(g)) > 1 else k for k, g in groupby(a)]
结果:
[(0, 'a'), 'b', (0, 'd'), (0, 'c')]
但我想看:
[(3, 'a'), 'b', (2, 'd'), (3, 'c')]
这种行为的原因是什么?
当您在 itertools._grouper
对象上调用 list()
时,您会耗尽该对象。由于您执行了两次,因此第二个实例的长度为 0。
第一个:
if len(list(g))
现在已经筋疲力尽了。那么:
(len(list(g)), k))
它的长度为 0。
您可以在 list
理解中嵌套一个 generator/comprehension 来耗尽对象并在处理之前保存相关数据:
>>> [(y,x) if y>1 else x for x,y in ((k, len(list(g))) for k, g in groupby(a))]
[(3, 'a'), 'b', (2, 'd'), (3, 'c')]
您需要确保 g
的元素只被消耗一次:
>>> print [(len(list(g)), k) if len(list(g)) > 1 else k for k, g in ((k, list(g)) for k, g in groupby(a))]
[(3, 'a'), 'b', (2, 'd'), (3, 'c')]
此代码还将遍历 k, g in groupby(a)
,但会将 g
转换为列表对象。然后,其余代码可以根据需要多次访问 g
(以检查长度),而无需使用结果。
在进行此更改之前,g
是一个 itertools._grouper
对象,这意味着您只能迭代 g
一次。之后它将为空,您将无法再次对其进行迭代。这就是您在结果中看到长度为 0 的原因。