我一直在以简单的方式循环遍历列表的内容以获取用户输入:
for n in [ 1, 2, 3, 4 ]:
command = raw_input ( "%d >> " % (n) )
...
我想实现一个撤销功能,这意味着将迭代“倒回”到之前的值。这是一种天真的方法,它确实减少了n的值,但随后跳过了原始值,因为列表中的内部指针没有改变:
for n in [ 1, 2, 3, 4 ]:
if f(n):
n -= 1
...
在docs中我看到了iterator.next(),但是没有iterator.last()。我想我可以通过整数索引切换到访问列表成员,并通过自己操纵索引来手动循环,这不是那么威胁,但有更好的方法吗?
答案 0 :(得分:8)
在Python中没有明显的方法可以做到这一点,但是很容易制作支持回溯的自己的迭代器。例如,下面是“可搜索”迭代器。寻求相对0重复相同的元素,或相对-1返回前一个元素。
NB因为这种迭代方式不能享受“保证前进的进步”,所以它更容易出现无限循环。
class SeekableIterator(object):
"""An iterator that supports seeking backwards or forwards."""
def __init__(self, iterable):
"""Make a SeekableIterator over an iterable collection."""
self.iterable = iterable
self.index = None
def __iter__(self):
"""Start the iteration."""
self.index = 0
return self
def next(self):
"""Return the next item in the iterator."""
try:
value = self.iterable[self.index]
self.index += 1
return value
except IndexError:
raise StopIteration
def seek(self, n, relative=False):
"""Adjust the loop counter, either relatively or to an absolute index.
Note that seeking 0 replays the current item. Seeking -1 goes to
the previous item. If the adjustment pushes the index outside the
iterable's bounds, raise an index error."""
if relative:
self.index += n - 1
# NB index already advanced one in next(), so subtracting one here
else:
self.index = n
if self.index < 0 or self.index >= len(self.iterable):
raise IndexError
if __name__ == '__main__':
import random
def prob(percent):
"""Return True with roughly the given probability, else False"""
return random.random() <= (percent * 1.0 / 100.0)
seeker = SeekableIterator([1, 2, 3, 4])
for n in seeker:
print "n:", n
if prob(50):
if prob(50):
print "\tREDO - seeking 0"
seeker.seek(0, relative=True)
elif n > 1:
print "\tUNDO - seeking -1"
seeker.seek(-1, relative=True)
以下是输出示例:
n: 1
n: 2
n: 3
n: 4
REDO - seeking 0
n: 4
REDO - seeking 0
n: 4
UNDO - seeking -1
n: 3
n: 4
答案 1 :(得分:3)
使用While
循环:
lis = [1, 2, 3, 4]
i = 0
while i < len(lis):
if some_condition:
print(lis[i])
i += 1
elif some_other_condition:
print(lis[i])
i -= 1
答案 2 :(得分:1)
共识是,不,没有办法让python迭代器回溯。该主题有更多信息:
Making a python iterator go backwards?
但是,您可能有一些运气重组您的循环格式略有不同。考虑以下pythonlike伪代码:
unprocessed = [1,2,3,...]
processed = []
traverse(unprocessed, processed, processor_function):
item = unprocessed.head()
unprocessed = unprocessed.tail()
processed.prepend(item)
if processor_function != None:
processor_function(item)
如果需要,您的主循环逻辑可以按任意顺序调用遍历,切换已处理和未处理,以模拟向后迭代。您可以传递所需的任何处理功能,包括传递None
以简单地跳过处理。处理完所有元素后,列表将如下所示:
unprocessed = []
processed = [...,3,2,1]
这是一种图灵机。 “读头”总是在第一个列表的第一个元素之上,读头的“右”的所有元素都在第一个列表中,索引随距离递增,所有元素到读取的“左”在第二个列表中,索引随距离递增。 “最接近”读头的元素是靠近每个列表开头的元素。