2012-01-21 42 views
17

Nói rằng tôi có một danh sách,Pythonic Thông tư Danh sách

l = [1, 2, 3, 4, 5, 6, 7, 8] 

Tôi muốn lấy các chỉ số của một phần tử tùy ý và các giá trị của các nước láng giềng. Ví dụ:

i = l.index(n) 
j = l[i-1] 
k = l[i+1] 

Tuy nhiên, đối với trường hợp cạnh khi i == len(l) - 1 điều này không thành công. Vì vậy, tôi nghĩ tôi chỉ quấn quanh,

if i == len(l) - 1: 
    k = l[0] 
else: 
    k = l[i+1] 

Có cách nào để làm điều này không?

+0

Bạn có muốn có một hành vi đặc biệt ngay cả khi chỉ mục nhỏ hơn 0 hoặc lớn hơn độ dài của danh sách không? – jimifiki

+0

Chỉ để quấn quanh. Tôi luôn luôn muốn 'j' và' k' chỉ vào một cái gì đó. Và tôi muốn có thể duyệt toàn bộ danh sách qua 'j' hoặc' k'. – john

+0

bạn chấp nhận một câu trả lời không quan tâm đến các chỉ số ngoài phạm vi ... – jimifiki

Trả lời

32

Bạn có thể sử dụng toán tử modulo!

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

j = l[jIndex] 
k = l[kIndex] 

Hoặc, ít chi tiết:

k = l[(i + 1) % len(l)] 
+4

Một nhận xét ngẫu nhiên: lưu ý rằng nếu 0 <= i

6

Cách điển hình để phù hợp với giá trị cho một phạm vi nhất định là sử dụng % điều hành:

k = l[(i + 1) % len(l)] 
18

Cách dễ nhất để quấn xung quanh một danh sách dài cố định là với các nhà điều hành (modulo)%

list_element = my_list[idx % len(my_list)] 

nhưng dù sao nhìn vào http://docs.python.org/library/itertools.html

from itertools import cycle 

for p in cycle([1,2,3]): 
    print "endless cycle:", p 
+1

+1 cho itertools.cycle – Eugen

0

Trong trường hợp bạn không muốn quấn quanh, câu trả lời Pythonic nhất sẽ là sử dụng lát. Thiếu hàng xóm thay thế bằng Không. Ví dụ:

def nbrs(l, e): 
    i = l.index(e) 
    return (l[i-1:i] + [None])[0], (l[i+1:i+2] + [None])[0] 

Đây là cách các chức năng có thể làm việc:

>>> 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 
0
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) 

cư xử như sau

>>> env (a, 2,1) 
[13, 2, 3] 
>>> env (a,13,2) 
[7, 11, 13, 2, 3] 
>>> env (a,7,0) 
[7] 
1

Nếu bạn muốn nó như là một lớp, tôi whipped lên này nhanh chóng CircularList:

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

    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) 

Nó hỗ trợ cắt, vì vậy

CircularList(range(10))[1:100] == [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8] 
0

Sử dụng phương pháp modulo mà người khác đã đề cập tôi đã tạo ra một lớp học với một tài sản mà thực hiện một danh sách tròn.

class 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 
Các vấn đề liên quan