Pythonic循环清单

joh*_*ohn 22 python list

说我有一个清单,

l = [1, 2, 3, 4, 5, 6, 7, 8]
Run Code Online (Sandbox Code Playgroud)

我想获取任意元素的索引及其邻居的值.例如,

i = l.index(n)
j = l[i-1]
k = l[i+1]
Run Code Online (Sandbox Code Playgroud)

但是,对于边缘情况,当i == len(l) - 1这失败.所以我以为我只是把它包起来

if i == len(l) - 1:
    k = l[0]
else:
    k = l[i+1]
Run Code Online (Sandbox Code Playgroud)

有没有pythonic方式来做到这一点?

voi*_*hos 38

你可以使用模运算符!

i = len(l) - 1
jIndex = (i - 1) % len(l)
kIndex = (i + 1) % len(l)

j = l[jIndex]
k = l[kIndex]
Run Code Online (Sandbox Code Playgroud)

或者,减少冗长:

k = l[(i + 1) % len(l)]
Run Code Online (Sandbox Code Playgroud)

  • 随机评论:注意如果0 <= i <len(l),那么`l [(i + 1)%len(l)]`也可以写成l [i - (len(l)-1) ]`,避免使用模数.(它给出一个通常为负的索引,这意味着从结尾开始计算,但其值是正确的.) (6认同)

max*_*axp 25

包裹固定长度列表的最简单方法是使用%(modulo)运算符

list_element = my_list[idx % len(my_list)]
Run Code Online (Sandbox Code Playgroud)

但无论如何看看 http://docs.python.org/library/itertools.html

from itertools import cycle

for p in cycle([1,2,3]):
  print "endless cycle:", p
Run Code Online (Sandbox Code Playgroud)


Ism*_*awi 6

将值拟合到特定范围的典型方法是使用%运算符:

k = l[(i + 1) % len(l)]
Run Code Online (Sandbox Code Playgroud)


ioi*_*red 5

如果你想把它作为一个类,我创建了这个快速的 CircularList:

import operator

class CircularList(list):
    def __getitem__(self, x):
        if isinstance(x, slice):
            return [self[x] for x in self._rangeify(x)]

        index = operator.index(x)
        try:
            return super().__getitem__(index % len(self))
        except ZeroDivisionError:
            raise IndexError('list index out of range')

    def _rangeify(self, slice):
        start, stop, step = slice.start, slice.stop, slice.step
        if start is None:
            start = 0
        if stop is None:
            stop = len(self)
        if step is None:
            step = 1
        return range(start, stop, step)
Run Code Online (Sandbox Code Playgroud)

它支持切片,所以

CircularList(range(5))[1:10] == [1, 2, 3, 4, 0, 1, 2, 3, 4]
Run Code Online (Sandbox Code Playgroud)