쌍을 이루는 순환 파이썬 'for'루프
한 쌍의 요소를 다시 조정하여 목록을 반복하는 멋진 Python 방법이 있습니까? 마지막 요소는 첫 번째 요소와 쌍을 이루어야합니다.
예를 들어 [1, 2, 3] 목록이있는 경우 다음 쌍을 얻고 싶습니다.
- 1 ~ 2
- 2 ~ 3
- 3-1
쌍으로 목록에 액세스하는 Python 방식은 다음과 같습니다 zip(L, L[1:])
. 마지막 항목을 첫 번째 항목에 연결하려면 :
>>> L = [1, 2, 3]
>>> zip(L, L[1:] + L[:1])
[(1, 2), (2, 3), (3, 1)]
나는 이것을 달성하기 위해 deque
with zip
를 사용할 것 입니다.
>>> from collections import deque
>>>
>>> l = [1,2,3]
>>> d = deque(l)
>>> d.rotate(-1)
>>> zip(l, d)
[(1, 2), (2, 3), (3, 1)]
설명서 에서 pairwise
레시피를 약간 수정했습니다 .itertools
def pairwise_circle(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ... (s<last>,s0)"
a, b = itertools.tee(iterable)
first_value = next(b, None)
return itertools.zip_longest(a, b,fillvalue=first_value)
이것은 단순히 첫 번째 값에 대한 참조를 유지하고 두 번째 반복자가 소진되면 zip_longest
마지막 위치를 첫 번째 값으로 채 웁니다.
(또한 생성기와 같은 반복기뿐만 아니라 목록 / 튜플과 같은 반복자에서도 작동합니다.)
참고 배리의 솔루션은 @ 하나 개의 요소 이상으로 확장 할 정말이 유사하지만 내 의견으로는 조금 이해하기 쉽고 쉽다.
나는 다음 itertools.cycle
과 짝 을 이룰 것이다 zip
.
import itertools
def circular_pairwise(l):
second = itertools.cycle(l)
next(second)
return zip(l, second)
cycle
마지막 값에서 첫 번째 값으로 반복하면서 인수의 값을 순서대로 생성하는 이터 러블을 반환합니다.
첫 번째 값을 건너 뛰므로 위치에서 시작합니다 1
( 0
아님).
다음으로, zip
원래의 변형되지 않은 목록을 사용합니다. zip
인수 iterable이 소진되면 중지되기 때문에 좋습니다.
이렇게하면 중간 목록이 생성 cycle
되지 않습니다. 원본에 대한 참조를 보유하지만 복사하지는 않습니다. zip
같은 방식으로 작동합니다.
그것은 입력이있는 경우이 중단 점에 유의하는 것이 중요 iterator
예로서, file
(또는 map
또는 zip
에서 파이썬-3 ) (을 통해 한 곳에서 전진으로, next(second)
자동으로 모든 다른 사람의 반복자를 진출하게됩니다). 이것은 itertools.tee
원래 iterable에 대해 두 개의 독립적으로 작동하는 반복자를 생성 하는를 사용하여 쉽게 해결됩니다 .
def circular_pairwise(it):
first, snd = itertools.tee(it)
second = itertools.cycle(snd)
next(second)
return zip(first, second)
tee
수 예를 들어 추가 스토리지 많은 양을 사용, 반환 된 반복자 중 하나가 다른 전에 사용하는 경우는 터치,하지만 우리는 오직 한 단계 차이를 가지고, 추가 저장을 최소화합니다.
더 효율적인 방법 (임시 목록을 작성하지 않음)이 있지만 이것이 가장 간결하다고 생각합니다.
> l = [1,2,3]
> zip(l, (l+l)[1:])
[(1, 2), (2, 3), (3, 1)]
목록 이해력을 사용 l[-1]
하고 마지막 요소 라는 사실을 활용합니다 .
>>> l = [1,2,3]
>>> [(l[i-1],l[i]) for i in range(len(l))]
[(3, 1), (1, 2), (2, 3)]
그런 식으로 임시 목록이 필요하지 않습니다.
쌍을 이루는 순환 파이썬 'for'루프
수락 된 답변이 마음에 들면
zip(L, L[1:] + L[:1])
다음을 사용하여 의미 상 동일한 코드로 훨씬 더 많은 메모리 라이트를 사용할 수 있습니다 itertools
.
from itertools import islice, chain #, izip as zip # uncomment if Python 2
그리고 이것은 원래 목록 이외의 메모리에있는 모든 것을 거의 구체화하지 않습니다 (목록이 상대적으로 크다고 가정).
zip(l, chain(islice(l, 1, None), islice(l, None, 1)))
사용하려면 다음과 같이 사용하십시오 (예 : 목록 사용).
>>> list(zip(l, chain(islice(l, 1, None), islice(l, None, 1))))
[(1, 2), (2, 3), (3, 1)]
이것은 모든 너비로 확장 가능하게 만들 수 있습니다.
def cyclical_window(l, width=2):
return zip(*[chain(islice(l, i, None), islice(l, None, i)) for i in range(width)])
및 사용법 :
>>> l = [1, 2, 3, 4, 5]
>>> cyclical_window(l)
<itertools.izip object at 0x112E7D28>
>>> list(cyclical_window(l))
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 1)]
>>> list(cyclical_window(l, 4))
[(1, 2, 3, 4), (2, 3, 4, 5), (3, 4, 5, 1), (4, 5, 1, 2), (5, 1, 2, 3)]
와 itertools.tee
함께 무제한 생성cycle
tee
중복 순환 객체를 만드는 것을 방지하기 위해 사용할 수도 있습니다 .
from itertools import cycle, tee
ic1, ic2 = tee(cycle(l))
next(ic2) # must still queue up the next item
그리고 지금:
>>> [(next(ic1), next(ic2)) for _ in range(10)]
[(1, 2), (2, 3), (3, 1), (1, 2), (2, 3), (3, 1), (1, 2), (2, 3), (3, 1), (1, 2)]
이것은의 예상 사용 매우 효율적 iter
으로 next
, 그리고 우아한 사용 cycle
, tee
및 zip
.
작업 을 저장 하지 않고 메모리를 최대로 사용하여 컴퓨터가 정지 할 시간이없는 한 cycle
직접 전달하지 마십시오. list
운이 좋으면 잠시 후 OS가 컴퓨터를 중단하기 전에 프로세스를 종료합니다. .
순수 파이썬 내장 함수
마지막으로 표준 lib 가져 오기는 없지만 원본 목록의 길이까지만 작동합니다 (그렇지 않으면 IndexError).
>>> [(l[i], l[i - len(l) + 1]) for i in range(len(l))]
[(1, 2), (2, 3), (3, 1)]
모듈로를 사용하여 계속할 수 있습니다.
>>> len_l = len(l)
>>> [(l[i % len_l], l[(i + 1) % len_l]) for i in range(10)]
[(1, 2), (2, 3), (3, 1), (1, 2), (2, 3), (3, 1), (1, 2), (2, 3), (3, 1), (1, 2)]
이 문제를 해결하는 방법이 얼마나 많은지 놀랍습니다.
여기 하나 더 있습니다. 당신이 사용할 수있는 pairwise
대신에 완봉의 조리법을 b
, chain
당신은 이미 떨어져 펑하는 첫 번째 요소로. cycle
하나의 추가 값만 필요할 때는 필요하지 않습니다 .
from itertools import chain, izip, tee
def pairwise_circle(iterable):
a, b = tee(iterable)
first = next(b, None)
return izip(a, chain(b, (first,)))
I like a solution that does not modify the original list and does not copy the list to temporary storage:
def circular(a_list):
for index in range(len(a_list) - 1):
yield a_list[index], a_list[index + 1]
yield a_list[-1], a_list[0]
for x in circular([1, 2, 3]):
print x
Output:
(1, 2)
(2, 3)
(3, 1)
I can imagine this being used on some very large in-memory data.
This one will work even if the list l
has consumed most of the system's memory. (If something guarantees this case to be impossible, then zip as posted by chepner is fine)
l.append( l[0] )
for i in range( len(l)-1):
pair = l[i],l[i+1]
# stuff involving pair
del l[-1]
or more generalizably (works for any offset n
i.e. l[ (i+n)%len(l) ]
)
for i in range( len(l)):
pair = l[i], l[ (i+1)%len(l) ]
# stuff
provided you are on a system with decently fast modulo division (i.e. not some pea-brained embedded system).
There seems to be a often-held belief that indexing a list with an integer subscript is un-pythonic and best avoided. Why?
This is my solution, and it looks Pythonic enough to me:
l = [1,2,3]
for n,v in enumerate(l):
try:
print(v,l[n+1])
except IndexError:
print(v,l[0])
prints:
1 2
2 3
3 1
The generator function version:
def f(iterable):
for n,v in enumerate(iterable):
try:
yield(v,iterable[n+1])
except IndexError:
yield(v,iterable[0])
>>> list(f([1,2,3]))
[(1, 2), (2, 3), (3, 1)]
How about this?
li = li+[li[0]]
pairwise = [(li[i],li[i+1]) for i in range(len(li)-1)]
from itertools import izip, chain, islice
itr = izip(l, chain(islice(l, 1, None), islice(l, 1)))
(위와 같이 @ jf-sebastian의 "zip"답변 이 있지만 itertools를 사용합니다.)
NB : @ 200_success의 유용한 넛지가 수정 되었습니다 . 이전 :
itr = izip(l, chain(l[1:], l[:1]))
또 다른 시도
>>> L = [1,2,3]
>>> zip(L,L[1:]) + [(L[-1],L[0])]
[(1, 2), (2, 3), (3, 1)]
너무 많은 메모리를 사용하지 않으려면 내 솔루션을 시도해 볼 수 있습니다.
[(l[i], l[(i+1) % len(l)]) for i, v in enumerate(l)]
조금 느리지 만 메모리를 덜 소비합니다.
L = [1, 2, 3] a = zip (L, L [1 :] + L [: 1]) for i in a : b = list (i) print b
이것은 조합이 일을 할 것 같습니다.
from itertools import combinations
x=combinations([1,2,3],2)
이것은 발전기를 산출 할 것입니다. 그런 다음 반복 할 수 있습니다.
for i in x:
print i
결과는 다음과 같습니다.
(1, 2)
(1, 3)
(2, 3)
참고 URL : https://stackoverflow.com/questions/36917042/pairwise-circular-python-for-loop
'Nice programing' 카테고리의 다른 글
WPF : 응용 프로그램의 중앙에 표시 할 대화 상자 위치를 설정하는 방법은 무엇입니까? (0) | 2020.10.17 |
---|---|
C ++ 11에서 사용되지 않는 매개 변수 (0) | 2020.10.17 |
자바 스크립트에서 배열의 중복 값을 계산하는 방법 (0) | 2020.10.17 |
목록에 하나의 진실한 값만 있는지 어떻게 확인할 수 있습니까? (0) | 2020.10.17 |
std :: multimap의 차이점은 무엇입니까 (0) | 2020.10.16 |