我正在尝试使用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]
有人能解释我的代码有什么问题并提供有效的解决方案吗?感谢。
答案 0 :(得分:8)
itertools
提供的功能可以完全满足您的需求。来自the Python Standard Library,
itertools。
islice
( iterable [, start ], stop [,步骤])创建一个从迭代中返回所选元素的迭代器。如果 start 非零,则跳过iterable中的元素,直到达到 start 。之后,除非将步骤设置为大于导致跳过项目的步骤,否则将连续返回元素。如果 stop 是
None
,则迭代继续,直到迭代器耗尽,如果有的话;否则,它会停在指定的位置。
>>> 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]
答案 1 :(得分:3)
predicate
的{{1}}参数应该是一个接受单个参数的函数,itertools.dropwhile
只是一个语句。在Python 2.x上,这将始终评估为False,因为enumerate < 3
,而在Python 3.x上,它将导致"type" > "int"
。
以下是您可以更改代码的方法,并仍使用TypeError: unorderable types: type() < int()
:
dropwhile
请注意,必须在iterable上调用>>> 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)]
,以便我们可以创建一个使用索引来确定是否删除当前值的lambda,但这意味着结果是{{ 1}}元组而不仅仅是值。我还将比较更改为enumerate
,因为您希望从(index, value)
开始,这是< 4
的第四个元素。
更好的选择是在Deokhwan's answer中使用14
。
答案 2 :(得分:1)
此处的其他一些答案很有帮助,但他们并未准确提供所要求的结果。接受的答案解释了有用的itertools.islice()
,但如果使用itertools.dropwhile()
是必需的,那么它就不太对了。其他一些答案也不必要地复杂。
一个简单的解决方案可能比预期更容易找到。例如:
list(dropwhile(lambda x: x < 14, xrange(10, 20)))
我将其包含在list()
中,因为请求的具体结果是[14, 15, 16, 17, 18, 19]
。可以删除该部分以使用dropwhile()
作为具有.next()
等的迭代器。因为这是一个迭代器,而不是range()
我使用了xrange()
,因为它是&#39;使用迭代器更有效率。 range()
可行,但可能效率不高。
我不确定目标的一部分是否也使用enumerate()
。也许是,但在示例中enumerate
被用作变量,而不是函数。获取所请求的结果并不是必需的,并且它不是问题的一部分,所以我认为它被错误地使用了。
正如其他人所指出的那样,问题中的例子并不需要使用理解来获得范围内的所有项目。这个答案也没有使用它。如果我们要进一步简化代码,获得所请求结果的最简单的解决方案是:
range(14, 20)
但这并不包括使用itertools.dropwhile()
的目标。
答案 3 :(得分:-1)
试试:
a = dropwhile(lambda x:x < 3, it)
参数必须是可调用的。
答案 4 :(得分:-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))
但是a
仍然是枚举对的列表(索引,值)。
更有效的方式可能看起来像这样:
class Counter:
def __init__(self):
self.n = 0
def __call__(self):
current = self.n
self.n += 1
return current
(见行动here,这很简单)
然后你就可以使用它:
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到结尾),但可以采用任何序列作为其参数。