2017-05-18 27 views
2

考慮以下列表:從概念循環列表中蟒創建兩個線性列表

>>> circle = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] 
>>> list(enumerate(circle)) 
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (4, 'e'), (5, 'f'), (6, 'g'), (7, 'h')] 

如果circle被概念化爲一循環列表即circle[0]連接到circle[7],給定一個start索引和end指數,其中start != end,我想構造兩個表示順時針和逆時針方向的線性遍歷順序。

取決於startend值,這裏就是我想出了:

案例1:start < end

>>> circle = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] 
>>> start, end = 1, 6 
>>> clockwise = circle[start:end+1] 
>>> clockwise 
['b', 'c', 'd', 'e', 'f', 'g'] 
>>> counter_clockwise = circle[start::-1] + circle[:end-1:-1] 
>>> counter_clockwise 
['b', 'a', 'h', 'g'] 

案例2:start > end

>>> circle = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] 
>>> start, end = 6, 1 
>>> clockwise = circle[start:] + circle[:end+1] 
>>> clockwise 
['g', 'h', 'a', 'b'] 
>>> counter_clockwise = circle[start:end-1:-1] 
>>> counter_clockwise 
['g', 'f', 'e', 'd', 'c', 'b'] 

是否有pythonic /更有效/更簡單的方式來構建這兩個列表?

+0

我沒有確切的答案給你,但Numpy(http://www.numpy.org/)在他們的數組實現中有一堆有用的功能。 – Xorgon

+0

@Xorgon對不起,不允許使用Numpy。 – veritasium42

回答

3

您可以使用itertools.cycle

import itertools 

circle = ['a', 'b', 'c', 'd', 'e', 'f', 
  'g', 'h'] 

def clockwise(start, end): 
    endless = itertools.cycle(circle) 
    if start > end: 
     end = start + (len(circle)-(start 
          -end)) 
    return [next(endless) for i in range 
      (end+1)][start:] 

def counter_clockwise(start, end): 
    endless = itertools.cycle(circle) 
    if end > start: 
     start = end + (len(circle)-(end 
          -start))  
    return [next(endless) for i in range 
      (start+1)][end:][::-1] 

# start < end: 
forward=clockwise(1, 6) 
b1=counter_clockwise(1, 6) 
#start > end: 
f1=clockwise(6, 1) 
backward=counter_clockwise(6, 1) 

print(forward) 
print(b1) 
print(f1) 
print(backward) 

輸出:

['b', 'c', 'd', 'e', 'f', 'g'] 
['b', 'a', 'h', 'g'] 
['g', 'h', 'a', 'b'] 
['g', 'f', 'e', 'd', 'c', 'b'] 
+0

但開始>結束時的情況如何? – kuro

1
import itertools 

def slice_it(circle,start,end,step=1): 
    if end < start and step > 0: 
     end = len(circle)+end 
    if step < 0: 
     return list(itertools.islice(itertools.cycle(circle),end,start,-1*step))[::-1] 
    return list(itertools.islice(itertools.cycle(circle),start,end,step)) 

circle = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] 

print slice_it(circle,6,1) 
print slice_it(circle,6,1,-1) 

可能?

0

您可以使用lambda表達式來創建順時針和逆時針方法並列出切片!

>>> clockwise = lambda circle, start, end: circle[start:] + circle[:end+1] if start > end else circle[start:end+1] 
>>> counter_clockwise = lambda circle, start, end : clockwise(circle, end, start)[::-1] 

這有點類似於你所嘗試過的,但是採用更加pythonic的方式和廣義的方式!

>>> clockwise(circle,1,6) 
['b', 'c', 'd', 'e', 'f', 'g'] 
>>> counter_clockwise(circle,1,6) 
['b', 'a', 'h', 'g'] 
>>> clockwise(circle,6,1) 
['g', 'h', 'a', 'b'] 
>>> counter_clockwise(circle,6,1) 
['g', 'f', 'e', 'd', 'c', 'b'] 
0

您可以使用dequecollections模塊來處理counter_clockwise conditon的某些部分,如本例中(你可以修改它或改進它,如果你想):

from collections import deque 

circle = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] 


clockwise = lambda x,start,end: x[start:end+1] if start < end else x[start:] + x[:end+1] 

def counter_clockwise(itertable, start, end): 
    if end > start: 
     a = deque(itertable[:start+1]) 
     b = deque(itertable[end:]) 
     a.rotate() 
     b.rotate() 
     # Or: 
     # return list(a.__iadd__(b)) 
     return list(a) + list(b) 

    if end < start: 
     return itertable[start:end-1:-1] 


print("start > end:") 
start, end = 6,1 
print(clockwise(circle, start, end)) 
print(counter_clockwise(circle, start, end)) 

print("start < end:") 
start, end = 1,6 
print(clockwise(circle, start, end)) 
print(counter_clockwise(circle, start, end)) 

輸出:

start > end: 
['g', 'h', 'a', 'b'] 
['g', 'f', 'e', 'd', 'c', 'b'] 
start < end: 
['b', 'c', 'd', 'e', 'f', 'g'] 
['b', 'a', 'h', 'g']