【问题标题】:Create two linear lists from a conceptual circular list in python从python中的概念循环列表创建两个线性列表
【发布时间】:2017-05-18 04:43:20
【问题描述】:

考虑以下列表:

>>> 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 的值,我得出以下结论:

案例一: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/更高效/更简单的方式来构建这两个列表?

【问题讨论】:

  • 我没有确切的答案给你,但是 Numpy (numpy.org) 在他们的数组实现中有很多有用的特性。
  • @Xorgon 抱歉,不允许使用 Numpy。

标签: python circular-list


【解决方案1】:

你可以使用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']

【讨论】:

  • 但是 start > end 的情况呢?
【解决方案2】:
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)

也许?

【讨论】:

    【解决方案3】:

    您可以使用 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]
    

    这与您尝试过的有点相似,但以更 Python 的方式和通用的方式!

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

    【讨论】:

      【解决方案4】:

      您可以使用collections 模块中的deque 来处理counter_clockwise 条件的某些部分,如此示例(您可以根据需要对其进行修改或改进):

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

      【讨论】:

        猜你喜欢
        • 2018-08-03
        • 2012-03-30
        • 1970-01-01
        • 2013-07-16
        • 2014-02-11
        • 1970-01-01
        • 2018-10-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多