2012-01-20 38 views
17

說我有一個列表:循環通過列表開始在某一個元素

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... 

我怎樣才能做到這一點?

回答

20

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] 
7

使用算術mod操作。假設你是從k位置開始,然後k應更新這樣的:

k = (k + 1) % len(l) 

如果你想從某一個元素開始,而不是指數,你總是可以看看它像k = l.index(x)其中X是期望項目。

2
import 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__'也可代替難看的拉姆達 –

+0

@gnibbler這將需要把'4'括號'(4).__ cmp__'。否則它不起作用(至少在Python 2.7.2中)。括號裏面看起來並不美麗。 – ovgolovin

+0

@gnibbler隨着Python 3中的,將採取用'__eq__',而不是'__cmp__'(沒有'__cmp__'作爲第3版)。 – ovgolovin

2

我不是導入模塊的時候,你可以做你自己的事情在幾行這樣的大風扇。這裏是我的解決方案沒有進口:

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 ... 
+4

'itertools'用'C'寫成。所以,除了它的口才外,它的速度相當快。 – ovgolovin

0

另一個奇怪的選擇是,通過列表循環可以向後完成。例如:

# 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 
相關問題