2

我试图使用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 

我正在寻找的输出是:

[14, 15, 16, 17, 18, 19]

谁能解释我的代码有什么问题并提供可行的解决方案?谢谢。

4

5 回答 5

8

itertools提供了一个功能,可以完全满足您的需求,甚至更多。来自Python 标准库

迭代工具。islice可迭代[,开始],停止[,步骤])

创建一个从可迭代对象中返回选定元素的迭代器。如果start不为零,则跳过 iterable 中的元素,直到到达start。之后,元素将连续返回,除非step设置为高于 1 导致项目被跳过。如果stopNone,则迭代继续,直到迭代器耗尽(如果有的话);否则,它会停在指定位置。

>>> import itertools
>>> it = (i for i in range(10, 20)) # it = xrange(10, 20)
>>> a = itertools.islice(it, 4, None)
>>> list(a)
[14, 15, 16, 17, 18, 19]
于 2012-08-22T21:51:21.870 回答
3

to的predicate参数itertools.dropwhile应该是一个接受单个参数的函数,enumerate < 3只是一个语句。在 Python 2.x 上,这将始终评估为 False "type" > "int",因为在 Python 3.x 上,它将导致TypeError: unorderable types: type() < int().

以下是更改代码并仍然使用的方法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)]

请注意,enumerate必须在可迭代对象上调用它,以便我们可以创建一个使用索引来确定是否删除当前值的 lambda,但这意味着结果是一个(index, value)元组列表,而不仅仅是值。我还将比较更改为,< 4因为您想从 开始14,这是 的第四个元素it

更好的选择是itertools.isliceDeokhwan 的回答中使用。

于 2012-08-22T21:56:14.317 回答
1

这里的其他一些答案很有帮助,但它们并没有给出所要求的结果。接受的答案解释了有用的itertools.islice(),但如果 usingitertools.dropwhile()是一个要求,那么它就不太对了。其他一些答案不必要地复杂。

一个简单的解决方案可能比预期更容易找到。例如:

list(dropwhile(lambda x: x < 14, xrange(10, 20)))

我把这个包裹起来,list()因为要求的具体结果是[14, 15, 16, 17, 18, 19]. 可以删除该部分以dropwhile()用作迭代器.next(),等等。因为这是一个迭代器,而不是range()我使用xrange()的,因为使用迭代器更有效。 range()会起作用,但可能效率不高。

我不确定目标的一部分是否也是使用enumerate()。也许是这样,但在示例enumerate中被用作变量,而不是函数。枚举不是获得请求的结果所必需的,它不是问题的一部分,所以我认为它被错误地使用了。

正如其他人指出的那样,问题中的示例不需要使用理解来获取范围中的所有项目。这个答案也没有使用它。如果我们要进一步简化代码,获得所需结果的最简单解决方案是:

range(14, 20)

但这不包括使用itertools.dropwhile().

于 2016-07-29T22:06:41.240 回答
-1

试试看:

a = dropwhile(lambda x:x < 3, it)  

参数必须是可调用的。

于 2012-08-22T21:50:45.517 回答
-1
 it = (i for i in range(10,20))

这有点多余,为什么不简单地使用range(10,20)(或xrange)?

您的代码中断是因为dropwhile需要一个函数作为其参数,并且您提供了一个布尔值(通过将函数enumerate与数字 3 进行比较来生成,这有点奇怪!)

使用枚举的解决方案可能如下所示:

a = dropwhile(lambda (i,val): i<3), enumerate(seq))

但 thena仍然是枚举对(索引,值)的列表。

一种更有效的方法可能如下所示:

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)

这使您可以使用dropwhile. 您的计数器实例为 seq 中的每个元素调用一次,并且每次都给出下一个数字。


也就是说,你最好使用itertools.islice

import itertools
a = itertools.islice(range(10, 20), 3, None)

islice允许您像列表切片一样进行切片(就像myList[3:]在这种情况下,从元素 #3 到结尾),但可以将任何序列作为其参数。

于 2012-08-22T22:01:33.313 回答