Python itertools.dropwhile的困难
我正在尝试使用Python itertools.dropwhile的困难,python,itertools,Python,Itertools,我正在尝试使用itertools.dropwhile仅从生成器返回第三个元素之后的元素,但我遇到了一些问题: from itertools import dropwhile it = (i for i in range(10,20)) a = dropwhile(enumerate < 3, it) next(a) TypeError: 'bool' object is not callable 有人能解释我的代码有什么问题并提供一个有效的解决方
itertools.dropwhile
仅从生成器返回第三个元素之后的元素,但我遇到了一些问题:
from itertools import dropwhile
it = (i for i in range(10,20))
a = dropwhile(enumerate < 3, it)
next(a)
TypeError: 'bool' object is not callable
有人能解释我的代码有什么问题并提供一个有效的解决方案吗?谢谢。试试:
a = dropwhile(lambda x:x < 3, it)
a=dropwhile(λx:x<3,it)
参数必须是可调用的。
itertools
提供了一个函数,该函数完全可以执行您想要的功能,并且可以执行更多操作。从
itertools.islice
(iterable[,start],stop[,step])
生成一个迭代器,从iterable返回选定的元素。如果start为非零,则将跳过iterable中的元素,直到到达start。之后,元素将连续返回,除非步骤设置高于导致跳过项的步骤。如果stop为None
,则迭代将继续,直到迭代器耗尽(如果有);否则,它将停止在指定位置
导入itertools
>>>它=(范围(10,20)内的i表示i)#它=范围(10,20)
>>>a=itertools.islice(it,4,无)
>>>名单(a)
[14, 15, 16, 17, 18, 19]
itertools.drop的谓词参数应该是一个接受单个参数的函数,枚举<3
只是一个语句。在Python2.x上,这将始终计算为False,因为在Python3.x上,这将导致类型错误:无序类型:type()
以下是如何更改代码并仍然使用dropwhile的方法:
>>> it = (i for i in range(10, 20))
>>> a = dropwhile(lambda i_v: i_v[0] < 4, enumerate(it))
>>> list(a)
[(4, 14), (5, 15), (6, 16), (7, 17), (8, 18), (9, 19)]
>>it=(范围(10,20)内的i代表i)
>>>a=dropwhile(lambda i_v:i_v[0]<4,枚举(it))
>>>名单(a)
[(4, 14), (5, 15), (6, 16), (7, 17), (8, 18), (9, 19)]
请注意,必须对iterable调用枚举
,以便我们可以创建一个lambda,该lambda使用索引确定是否删除当前值,但这意味着结果是(索引,值)
元组列表,而不仅仅是值。我还将比较改为<4
,因为您希望从14
开始,这是it
的第四个元素
更好的选择是使用itertools.islice
,如中所示
这有点多余,为什么不简单地使用range(10,20)
(或者xrange
)
您的代码中断是因为dropwhile
需要一个函数作为其参数,而您提供的是一个布尔值(通过将函数enumerate
与数字3进行比较,这有点奇怪!)
使用enumerate的解决方案可能如下所示:
a = dropwhile(lambda (i,val): i<3), enumerate(seq))
(在行动中看到它,它非常简单)
然后你可以像这样使用它:
c = Counter()
a = dropwhile(lambda elem: c() < 3, seq)
islice
允许您像列表切片一样进行切片(在本例中,类似于myList[3://code>,从元素#3到结尾),但可以将任何序列作为其参数。这里的一些其他答案很有帮助,但它们没有给出所需的确切结果。公认的答案解释了有用的itertools.islice()。其他一些答案是不必要的复杂
一个简单的解决方案可能比预期的更容易找到。例如:
list(dropwhile(lambda x: x < 14, xrange(10, 20)))
但这还不包括使用itertools.dropwhile()
的目标,因为13
也会出现在输出中吗?(范围(10,20)中的i代表i)是多余的。您可以按原样迭代范围(10,20)
。是的,dropwhile
正在比较项目的值。使用islice
处理索引。dropwhile中函数的两个参数不起作用,在Python 2.x中,可以使用lambda(i,val):…
但这是Python 3.x上的一个语法错误。我喜欢计数器
方法,但可能会使用它,而不是创建一个新类。感谢您指出缺少paren,是的,我有点怀念py3中的tuple解包。感谢您也提到了count
,尽管我只是建议使用计数器类进行说明,因为islice
是这里的实际解决方案。谢谢,我没有想到使用islice
。当然,最干净的解决方案。@turtle:range(10,20)[4::
或range(14,20)
更好。调用list(result)
以获取Python 3上的列表。@J.F.Sebastianislice
更便于移植,因为Python 2中不支持xrange(10,20)[4://code>。我同意,仅在Python3中,您的范围(10,20)[4://code>更好。@DeokhwanKim:OP的代码是Python2<代码>范围(10,20)[4://code>在Python2上工作(因为range
返回一个列表)<代码>列表(范围(10,20)[4:])
适用于Python 3。但是我明白你的意思,如果你想得到一个迭代器,而不是序列。@J.F.Sebastian@turtle我对J.F.Sebastian最后的评论有点困惑。我的回答是基于这样的推测,即问题是如何从迭代器中获取其子迭代器,(i代表范围(10,20))中的i
部分只是一个错误,在生成一个小代码片段时出现了这个错误。如果最终的目标只是从Python 2中的range()
中获取它的子列表,那么dropwhile
和islice
都是杀伤力过大的,列表切片绝对是一种方法,正如J.F.Sebastian所说。
class Counter:
def __init__(self):
self.n = 0
def __call__(self):
current = self.n
self.n += 1
return current
c = Counter()
a = dropwhile(lambda elem: c() < 3, seq)
import itertools
a = itertools.islice(range(10, 20), 3, None)
list(dropwhile(lambda x: x < 14, xrange(10, 20)))
range(14, 20)