假设我有一个列表,
l = [1, 2, 3, 4, 5, 6, 7, 8]
我想获取任意元素的索引及其相邻元素的值。例如:
i = l.index(n)
j = l[i-1]
k = l[i+1]
然而,对于当i == len(l) - 1
时的特殊情况则会失败。因此我想把它简单地处理一下,
if i == len(l) - 1:
k = l[0]
else:
k = l[i+1]
有没有一种 Pythonic 的方法来做这件事?
你可以使用取模运算符!
i = len(l) - 1
jIndex = (i - 1) % len(l)
kIndex = (i + 1) % len(l)
j = l[jIndex]
k = l[kIndex]
或者说,更简洁地说:
k = l[(i + 1) % len(l)]
l[(i + 1) % len(l)]
写为l[i - (len(l)-1)]
,从而避免使用取模操作。(它返回的索引往往是负数,这意味着从末尾开始计数,但其值是正确的。) - Armin Rigo(它给出的索引通常是负数,这意味着从末尾开始计数,但其值是正确的。)
? - user5319825用 %(取模)运算符对固定长度的列表进行环绕是最简单的方法。
list_element = my_list[idx % len(my_list)]
但无论如何,看看https://docs.python.org/library/itertools.html#itertools.cycle
from itertools import cycle
for p in cycle([1,2,3]):
print "endless cycle:", p
还请注意警告:请注意,该工具包成员可能需要大量的辅助存储空间(根据可迭代对象的长度)。
k = l[(i + 1) % len(l)]
如果你想要将它作为一个类,我已经快速编写了这个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)
它支持切片操作,所以
CircularList(range(5))[1:10] == [1, 2, 3, 4, 0, 1, 2, 3, 4]
a = CircularList([])
然后 a[0]
,我会得到一个 ZeroDivisionError 错误,这是错误的。你应该添加 except ZeroDivisionError: raise IndexError('list index out of range')
- Daniel Moskovichclass Circle:
"""Creates a circular array of numbers
>>> c = Circle(30)
>>> c.position
-1
>>> c.position = 10
>>> c.position
10
>>> c.position = 20
>>> c.position
20
>>> c.position = 30
>>> c.position
0
>>> c.position = -5
>>> c.position
25
>>>
"""
def __init__(self, size):
if not isinstance(size, int): # validating length
raise TypeError("Only integers are allowed")
self.size = size
@property
def position(self):
try:
return self._position
except AttributeError:
return -1
@position.setter
def position(self, value):
positions = [x for x in range(0, self.size)]
i = len(positions) - 1
k = positions[(i + value + 1) % len(positions)]
self._position = k
a = [2,3,5,7,11,13]
def env (l, n, count):
from itertools import cycle, islice
index = l.index(n) + len(l)
aux = islice (cycle (l), index - count, index + count + 1)
return list(aux)
表现如下
>>> env (a, 2,1)
[13, 2, 3]
>>> env (a,13,2)
[7, 11, 13, 2, 3]
>>> env (a,7,0)
[7]
如果您不想进行包装,最Pythonic的答案是使用切片。缺失的邻居将被替换为None。例如:
def nbrs(l, e):
i = l.index(e)
return (l[i-1:i] + [None])[0], (l[i+1:i+2] + [None])[0]
下面是这个函数的工作方式:
>>> nbrs([2,3,4,1], 1)
(4, None)
>>> nbrs([1,2,3], 1)
(None, 2)
>>> nbrs([2,3,4,1,5,6], 1)
(4, 5)
>>> nbrs([], 1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in nbrs
ValueError: 1 is not in list
j
和k
指向某些东西。而且我希望能够通过j
或k
遍历整个列表。 - johnk[10]
永远不会发生,因为l.index(n)
只会返回最大值为len(l) - 1
的东西,在这种情况下是i = 7
。我将i
增加了1
,就这样。虽然我没有明确地写出来,但我在l.index(n)
前面加上了if n in l
,并适当处理了错误。因此,接受的答案是这个特定问题的解决方案,但还是谢谢您的关注。 - john