假设我有一个列表:
l = [1, 2, 3, 4]
我希望您能循环访问它。通常情况下,它会执行以下操作:
1, 2, 3, 4, 1, 2, 3, 4, 1, 2...
我希望能够在循环中的某个特定点开始,不一定是按索引,而是可能匹配一个元素。比如说,如果我想从列表中任何一个等于4
的元素开始,那么输出将是:
4, 1, 2, 3, 4, 1, 2, 3, 4, 1...
我该如何完成这个任务?
看看 itertools 模块。它提供了所有必要的功能。
from itertools import cycle, islice, dropwhile
L = [1, 2, 3, 4]
cycled = cycle(L) # cycle thorugh the list 'L'
skipped = dropwhile(lambda x: x != 4, cycled) # drop the values until x==4
sliced = islice(skipped, None, 10) # take the first 10 values
result = list(sliced) # create a list from iterator
print(result)
输出:
[4, 1, 2, 3, 4, 1, 2, 3, 4, 1]
使用算术模运算符mod
。假设你从位置k
开始,那么k
应该像这样更新:
k = (k + 1) % len(l)
如果你想要从特定元素开始,而不是索引,你可以像这样查找它:k = l.index(x)
其中x是所需的项目。def cycle(my_list, start_at=None):
start_at = 0 if start_at is None else my_list.index(start_at)
while True:
yield my_list[start_at]
start_at = (start_at + 1) % len(my_list)
next
语句:>>> it1 = cycle([101,102,103,104])
>>> next(it1), next(it1), next(it1), next(it1), next(it1)
(101, 102, 103, 104, 101) # and so on ...
>>> it1 = cycle([101,102,103,104], start_at=103)
>>> next(it1), next(it1), next(it1), next(it1), next(it1)
(103, 104, 101, 102, 103) # and so on ...
itertools
是用 C
编写的,因此除了其优雅之外,它相当快速。 - ovgolovinimport itertools as it
l = [1, 2, 3, 4]
list(it.islice(it.dropwhile(lambda x: x != 4, it.cycle(l)), 10))
# returns: [4, 1, 2, 3, 4, 1, 2, 3, 4, 1]
所需的迭代器是:
it.dropwhile(lambda x: x != 4, it.cycle(l))
4
放在括号中(4).__cmp__
。否则它不起作用(至少在Python 2.7.2中是这样)。而且加上括号看起来也不太美观。 - ovgolovin__eq__
而不是__cmp__
(在版本3中没有__cmp__
)。 - ovgolovin4
和 .
之间加上空格了? - Duncan__ne__
或者__gt__
而不是__eq__
。@ovgolovin - Duncan4.__cmp__
,Python会将其解析为浮点数 4.
后跟一个标识符 __cmp__
,这是语法错误。另一方面,4 .__cmp__
是整数 4
,后跟一个句点表示属性引用和属性 __cmp__
。 - Duncan另一个奇怪的选项是可以反向循环列表。例如:
# Run this once
myList = ['foo', 'bar', 'baz', 'boom']
myItem = 'baz'
# Run this repeatedly to cycle through the list
if myItem in myList:
myItem = myList[myList.index(myItem)-1]
print myItem
嗯,http://docs.python.org/library/itertools.html#itertools.cycle 没有这样的起始元素。
也许你可以直接开始循环,并丢弃你不喜欢的第一个元素。
可以使用类似这样的东西:
def my_cycle(data, start=None):
k = 0 if not start else start
while True:
yield data[k]
k = (k + 1) % len(data)
然后运行:
for val in my_cycle([0,1,2,3], 2):
print(val)
本质上与之前的答案相同。我的错。
dropwhile
doesn't seem necessary here. You can instead uselist(islice(cycled, L.index(4), L.index(4) + 9))
- busybear