Answers:
其他答案仅适用于序列。
对于任何迭代,请跳过第一项:
itercars = iter(cars)
next(itercars)
for car in itercars:
# do work
如果要跳过最后一个,可以执行以下操作:
itercars = iter(cars)
# add 'next(itercars)' here if you also want to skip the first
prev = next(itercars)
for car in itercars:
# do work on 'prev' not 'car'
# at end of loop:
prev = car
# now you can do whatever you want to do to the last one on 'prev'
要跳过Python中的第一个元素,您只需编写
for car in cars[1:]:
# Do What Ever you want
或跳过最后一个元素
for car in cars[:-1]:
# Do What Ever you want
您可以将此概念用于任何序列。
跳过第一项的最佳方法是:
from itertools import islice
for car in islice(cars, 1, None):
# do something
在这种情况下,使用起点1和终点None调用islice,表示迭代器的结束。
为了能够从可迭代对象的末尾跳过项目,您需要知道其长度(对于列表而言总是可能的,但不一定可以迭代的所有内容)。例如,islice(cars,1,len(cars)-1)将跳过汽车列表中的第一项和最后一项。
islice很好地跳过任何可迭代项的开头和/或结尾的任意数量的项目,而不用知道长度或一次在内存中存储比绝对必要更多的项目。
islice是传递给的deque,而不是整个迭代器,它只是末尾要跳过的项目数的长度。它不会将整个迭代器存储在内存中。
这是一个更通用的生成器函数,它从可迭代对象的开头和结尾跳过任何数量的项目:
def skip(iterable, at_start=0, at_end=0):
it = iter(iterable)
for x in itertools.islice(it, at_start):
pass
queue = collections.deque(itertools.islice(it, at_end))
for x in it:
queue.append(x)
yield queue.popleft()
用法示例:
>>> list(skip(range(10), at_start=2, at_end=2))
[2, 3, 4, 5, 6, 7]
at_end == 0。
skip(xrange(10000000), 1)将使用at_end=0,因此参数to deque()将是islice(it, 0),它将仅消耗的零个元素it。这不会占用很多内存。
for item in do_not_use_list_as_a_name[1:-1]:
#...do whatever
list用作变量名
list可以重新绑定。这就是为什么您不应该(而不是不能)使用它。
基于@SvenMarnach的答案,但更简单并且不使用双端队列
>>> def skip(iterable, at_start=0, at_end=0):
it = iter(iterable)
it = itertools.islice(it, at_start, None)
it, it1 = itertools.tee(it)
it1 = itertools.islice(it1, at_end, None)
return (next(it) for _ in it1)
>>> list(skip(range(10), at_start=2, at_end=2))
[2, 3, 4, 5, 6, 7]
>>> list(skip(range(10), at_start=2, at_end=5))
[2, 3, 4]
另请注意,根据我的timeit结果,这比双端队列解决方案要快一点
>>> iterable=xrange(1000)
>>> stmt1="""
def skip(iterable, at_start=0, at_end=0):
it = iter(iterable)
it = itertools.islice(it, at_start, None)
it, it1 = itertools.tee(it)
it1 = itertools.islice(it1, at_end, None)
return (next(it) for _ in it1)
list(skip(iterable,2,2))
"""
>>> stmt2="""
def skip(iterable, at_start=0, at_end=0):
it = iter(iterable)
for x in itertools.islice(it, at_start):
pass
queue = collections.deque(itertools.islice(it, at_end))
for x in it:
queue.append(x)
yield queue.popleft()
list(skip(iterable,2,2))
"""
>>> timeit.timeit(stmt = stmt1, setup='from __main__ import iterable, skip, itertools', number = 10000)
2.0313770640908047
>>> timeit.timeit(stmt = stmt2, setup='from __main__ import iterable, skip, itertools, collections', number = 10000)
2.9903135454296716
tee(),您仍在为生成器在内存中创建整个列表,对吗?(您的it1)
如果cars是一个序列,你可以做
for car in cars[1:-1]:
pass
该more_itertools项目扩展itertools.islice到处理负指标。
例
import more_itertools as mit
iterable = 'ABCDEFGH'
list(mit.islice_extended(iterable, 1, -1))
# Out: ['B', 'C', 'D', 'E', 'F', 'G']
因此,您可以将它的slice元素优雅地应用于iterable的第一项和最后一项之间:
for car in mit.islice_extended(cars, 1, -1):
# do something
for n, i in enumerate(cars): if n!= 0: do something to i。逻辑是,它会向每个值添加一个“计数器”,然后您可以使用来定位if n == some_value。在此示例中,它将对i的每个实例(第一个实例除外)执行某些操作。