[python] 이전 및 다음 값에도 액세스하는 Python 루프

이전, 현재 및 다음 항목에 액세스하여 객체 목록을 반복하려면 어떻게해야합니까? 파이썬에서이 C / C ++ 코드처럼?

foo = somevalue;
previous = next = 0;

for (i=1; i<objects.length(); i++) {
    if (objects[i]==foo) {
        previous = objects[i-1];
        next = objects[i+1];
    }
}



답변

이것은 트릭을 할 것입니다.

foo = somevalue
previous = next_ = None
l = len(objects)
for index, obj in enumerate(objects):
    if obj == foo:
        if index > 0:
            previous = objects[index - 1]
        if index < (l - 1):
            next_ = objects[index + 1]

다음은 enumerate기능 에 대한 문서입니다 .


답변

지금까지의 솔루션은 목록 만 다루며 대부분은 목록을 복사하고 있습니다. 내 경험상 불가능한 일이 많다.

또한 목록에서 반복되는 요소를 가질 수 있다는 사실을 다루지 않습니다.

질문 제목은 ” 루프 내부의 이전 및 다음 값 “이지만 루프 내부에서 대부분의 답변을 실행하는 경우 각 요소에서 전체 목록을 다시 반복하여 검색하게됩니다.

그래서 방금 그 함수를 만들었습니다. itertools모듈을 사용하여 이터 러블을 분할 및 슬라이스하고 이전 및 다음 요소와 함께 튜플을 생성합니다. 코드가하는 일이 정확히 무엇인지는 아니지만 문제를 해결할 수 있기 때문에 살펴볼 가치가 있습니다.

from itertools import tee, islice, chain, izip

def previous_and_next(some_iterable):
    prevs, items, nexts = tee(some_iterable, 3)
    prevs = chain([None], prevs)
    nexts = chain(islice(nexts, 1, None), [None])
    return izip(prevs, items, nexts)

그런 다음 루프에서 사용하면 이전 및 다음 항목이 있습니다.

mylist = ['banana', 'orange', 'apple', 'kiwi', 'tomato']

for previous, item, nxt in previous_and_next(mylist):
    print "Item is now", item, "next is", nxt, "previous is", previous

결과 :

Item is now banana next is orange previous is None
Item is now orange next is apple previous is banana
Item is now apple next is kiwi previous is orange
Item is now kiwi next is tomato previous is apple
Item is now tomato next is None previous is kiwi

모든 크기 목록 (목록을 복사하지 않기 때문에)과 반복 가능한 목록 (파일, 세트 등)과 함께 작동합니다. 이렇게하면 시퀀스를 반복하고 루프 내에서 이전 및 다음 항목을 사용할 수 있습니다. 시퀀스에서 항목을 다시 검색 할 필요가 없습니다.

코드에 대한 간단한 설명 :

  • tee 입력 시퀀스에 대해 3 개의 독립 반복기를 효율적으로 만드는 데 사용됩니다.
  • chain두 시퀀스를 하나로 연결합니다. 여기에 단일 요소 시퀀스 [None]를 추가하는 데 사용 됩니다.prevs
  • islice첫 번째 요소를 제외한 모든 요소의 시퀀스를 만드는 chain데 사용되며 None끝에 a 를 추가하는 데 사용됩니다.
  • 이제 some_iterable다음과 같은 3 개의 독립적 인 시퀀스가 ​​있습니다 .
    • prevs: None, A, B, C, D, E
    • items: A, B, C, D, E
    • nexts: B, C, D, E, None
  • 마지막으로 izip3 개의 시퀀스를 3 개의 시퀀스로 변경하는 데 사용됩니다.

참고 izip모든 입력 순서가 소진 될때의 마지막 요소는, 그래서 중지 prevs마지막 요소가 될 것이라고 이러한 요소가 없습니다 – 올바른 무시됩니다 prev. 우리는 마지막 요소를 제거하려고 할 수 prevs있지만 izip의 동작은

또한 점에 유의 tee, izip, islicechain으로부터 온 itertools모듈; 즉석에서 (게으른) 입력 시퀀스에 대해 작동하므로 효율적으로 만들고 전체 시퀀스를 한 번에 메모리에 저장할 필요가 없습니다.

에서는 python 3가져 오는 동안 오류가 표시 됩니다 . 대신 izip사용할 수 있습니다 . 수입 할 필요는 , 그것은에 미리 정의되지 않는다 – 소스zipizipzippython 3


답변

목록 이해력을 사용하여 현재, 이전 및 다음 요소가있는 3- 튜플을 반환합니다.

three_tuple = [(current,
                my_list[idx - 1] if idx >= 1 else None,
                my_list[idx + 1] if idx < len(my_list) - 1 else None) for idx, current in enumerate(my_list)]


답변

내장 함수 만 사용하고 다른 오프셋으로 쉽게 확장 할 수 있기 때문에 이것이 어떻게 아직 나타나지 않았는지 모르겠습니다.

values = [1, 2, 3, 4]
offsets = [None] + values[:-1], values, values[1:] + [None]
for value in list(zip(*offsets)):
    print(value) # (previous, current, next)

(None, 1, 2)
(1, 2, 3)
(2, 3, 4)
(3, 4, None)


답변

다음은 경계 오류없이 생성기를 사용하는 버전입니다.

def trios(iterable):
    it = iter(iterable)
    try:
        prev, current = next(it), next(it)
    except StopIteration:
        return
    for next in it:
        yield prev, current, next
        prev, current = current, next

def find_prev_next(objects, foo):
    prev, next = 0, 0
    for temp_prev, current, temp_next in trios(objects):
        if current == foo:
            prev, next = temp_prev, temp_next
    return prev, next

print(find_prev_next(range(10), 1))
print(find_prev_next(range(10), 0))
print(find_prev_next(range(10), 10))
print(find_prev_next(range(0), 10))
print(find_prev_next(range(1), 10))
print(find_prev_next(range(2), 10))

경계 동작은 코드와 달리 첫 번째 또는 마지막 요소에서 “foo”를 찾지 않는다는 것입니다. 다시 말하지만, 경계 의미론은 이상하며 코드에서 파악하기 어렵습니다. 🙂


답변

파이썬> = 2.5 간결성을 위해 조건식 사용

def prenext(l,v) :
   i=l.index(v)
   return l[i-1] if i>0 else None,l[i+1] if i<len(l)-1 else None


# example
x=range(10)
prenext(x,3)
>>> (2,4)
prenext(x,0)
>>> (None,2)
prenext(x,9)
>>> (8,None)


답변

요소를 순환하고 싶은이 문제에 대한 해결책을 찾는 사람에게는 아래가 효과적 일 수 있습니다.

from collections import deque

foo = ['A', 'B', 'C', 'D']

def prev_and_next(input_list):
    CURRENT = input_list
    PREV = deque(input_list)
    PREV.rotate(-1)
    PREV = list(PREV)
    NEXT = deque(input_list)
    NEXT.rotate(1)
    NEXT = list(NEXT)
    return zip(PREV, CURRENT, NEXT)

for previous_, current_, next_ in prev_and_next(foo):
    print(previous_, current_, next)