답변:
pairwise()
(또는 grouped()
) 구현 이 필요합니다 .
파이썬 2의 경우 :
from itertools import izip
def pairwise(iterable):
"s -> (s0, s1), (s2, s3), (s4, s5), ..."
a = iter(iterable)
return izip(a, a)
for x, y in pairwise(l):
print "%d + %d = %d" % (x, y, x + y)
또는 더 일반적으로 :
from itertools import izip
def grouped(iterable, n):
"s -> (s0,s1,s2,...sn-1), (sn,sn+1,sn+2,...s2n-1), (s2n,s2n+1,s2n+2,...s3n-1), ..."
return izip(*[iter(iterable)]*n)
for x, y in grouped(l, 2):
print "%d + %d = %d" % (x, y, x + y)
Python 3에서는 izip
내장 zip()
함수로 대체하고을 삭제할 수 import
있습니다.
내 질문에 대한 그의 답변 에 대한 마 티노에 대한 모든 신용 은 목록을 한 번만 반복하고 프로세스에서 불필요한 목록을 만들지 않기 때문에 이것이 매우 효율적이라는 것을 알았습니다.
NB는 :이은과 혼동해서는 안 pairwise
조리법 파이썬의 자신의 itertools
문서 , 수율 s -> (s0, s1), (s1, s2), (s2, s3), ...
에 의해 지적 밖으로로서, @lazyr 의견이다.
Python 3 에서 mypy로 유형 검사를하고 싶은 사람들에게는 거의 추가되지 않습니다 .
from typing import Iterable, Tuple, TypeVar
T = TypeVar("T")
def grouped(iterable: Iterable[T], n=2) -> Iterable[Tuple[T, ...]]:
"""s -> (s0,s1,s2,...sn-1), (sn,sn+1,sn+2,...s2n-1), ..."""
return zip(*[iter(iterable)] * n)
s -> (s0,s1), (s1,s2), (s2, s3), ...
itertools
동일한 버전의 레시피 기능과 비교하여 버전의 절반 만 생산합니다 . 물론 당신은 더 빠릅니다 ...
izip_longest()
대신 대신 사용할 수 있습니다 izip()
. 예 : list(izip_longest(*[iter([1, 2, 3])]*2, fillvalue=0))
-> [(1, 2), (3, 0)]
. 도움이 되었기를 바랍니다.
두 요소의 튜플이 필요합니다.
data = [1,2,3,4,5,6]
for i,k in zip(data[0::2], data[1::2]):
print str(i), '+', str(k), '=', str(i+k)
어디:
data[0::2]
요소의 하위 집합 모음을 만드는 것을 의미합니다. (index % 2 == 0)
zip(x,y)
x 및 y 컬렉션에서 동일한 인덱스 요소로 튜플 컬렉션을 만듭니다.for i, j, k in zip(data[0::3], data[1::3], data[2::3]):
import
것은 그들 중 하나가 아닙니다.
>>> l = [1,2,3,4,5,6]
>>> zip(l,l[1:])
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]
>>> zip(l,l[1:])[::2]
[(1, 2), (3, 4), (5, 6)]
>>> [a+b for a,b in zip(l,l[1:])[::2]]
[3, 7, 11]
>>> ["%d + %d = %d" % (a,b,a+b) for a,b in zip(l,l[1:])[::2]]
['1 + 2 = 3', '3 + 4 = 7', '5 + 6 = 11']
zip
는 zip
Python 3에서 개체를 반환하며 , 첨자는 불가능합니다. 먼저 시퀀스 ( list
, tuple
등) 로 변환해야 하지만 "작동하지 않음" 은 약간의 확장입니다.
간단한 해결책.
l = [1, 2, 3, 4, 5, 6] 범위 (i, len (l), 2)의 i의 경우 : str (l [i]), '+', str (l [i + 1]), '=', str (l [i] + l [i + 1]) 인쇄
((l[i], l[i+1])for i in range(0, len(l), 2))
발전기의 경우 더 긴 튜플을 위해 쉽게 수정할 수 있습니다.
사용하는 모든 답변 zip
이 정확 하지만 기능을 직접 구현하면 더 읽기 쉬운 코드로 연결됩니다.
def pairwise(it):
it = iter(it)
while True:
try:
yield next(it), next(it)
except StopIteration:
# no more elements in the iterator
return
이 it = iter(it)
부분은 it
반복 가능한 것이 아니라 실제로 반복자 임을 보장합니다 . 경우 it
이미이 반복자이며,이 라인은 no-op입니다.
용법:
for a, b in pairwise([0, 1, 2, 3, 4, 5]):
print(a + b)
it
은 반복자 일 뿐이고 반복 가능하지 않은 경우에도 작동합니다 . 다른 솔루션은 시퀀스에 대해 두 개의 독립적 인 반복자를 만들 가능성에 의존하는 것 같습니다.
나는 이것이 더 우아한 방법이되기를 바랍니다.
a = [1,2,3,4,5,6]
zip(a[::2], a[1::2])
[(1, 2), (3, 4), (5, 6)]
성능에 관심이있는 경우 simple_benchmark
솔루션의 성능을 비교하기 위해 작은 벤치 마크 (내 라이브러리 사용 )를 수행했으며 패키지 중 하나의 기능을 포함했습니다.iteration_utilities.grouper
from iteration_utilities import grouper
import matplotlib as mpl
from simple_benchmark import BenchmarkBuilder
bench = BenchmarkBuilder()
@bench.add_function()
def Johnsyweb(l):
def pairwise(iterable):
"s -> (s0, s1), (s2, s3), (s4, s5), ..."
a = iter(iterable)
return zip(a, a)
for x, y in pairwise(l):
pass
@bench.add_function()
def Margus(data):
for i, k in zip(data[0::2], data[1::2]):
pass
@bench.add_function()
def pyanon(l):
list(zip(l,l[1:]))[::2]
@bench.add_function()
def taskinoor(l):
for i in range(0, len(l), 2):
l[i], l[i+1]
@bench.add_function()
def mic_e(it):
def pairwise(it):
it = iter(it)
while True:
try:
yield next(it), next(it)
except StopIteration:
return
for a, b in pairwise(it):
pass
@bench.add_function()
def MSeifert(it):
for item1, item2 in grouper(it, 2):
pass
bench.use_random_lists_as_arguments(sizes=[2**i for i in range(1, 20)])
benchmark_result = bench.run()
mpl.rcParams['figure.figsize'] = (8, 10)
benchmark_result.plot_both(relative_to=MSeifert)
따라서 외부 의존성이없는 가장 빠른 솔루션을 원한다면 Johnysweb이 제공 한 접근 방식을 사용해야합니다 (작성 시점에서 가장 찬성되고 인정 된 답변입니다).
추가 종속성을 신경 쓰지 않으면 grouper
from iteration_utilities
이 약간 빠를 것입니다.
일부 접근 방식에는 여기에서 설명하지 않은 제한 사항이 있습니다.
예를 들어, 일부 솔루션은 시퀀스 (즉, 목록, 문자열 등)에만 작동합니다. 예를 들어 Margus / pyanon / taskinoor 솔루션은 인덱싱을 사용하고 다른 솔루션은 Johnysweb /과 같은 반복 가능 (시퀀스 및 생성기, 반복기)에서 작동합니다. mic_e / my 솔루션.
그런 다음 Johnysweb은 2 이외의 다른 크기에서도 작동하는 솔루션을 제공했지만 다른 답변은 그렇지 않습니다 ( iteration_utilities.grouper
요소 수를 "그룹"으로 설정할 수도 있음).
그런 다음 목록에 홀수 개의 요소가있는 경우 어떻게해야하는지에 대한 질문도 있습니다. 나머지 품목을 기각해야합니까? 크기가 일정하도록 목록을 채워야합니까? 나머지 품목을 단일 품목으로 반품해야합니까? 다른 대답은이 요점을 직접 다루지 않지만, 아무것도 간과하지 않은 경우 나머지 항목을 무시 해야하는 접근법을 따르지 않습니다 (실무자가 답변을 제외하고 실제로 예외가 발생 함).
으로 grouper
당신은 당신이 원하는 무엇을 결정할 수 있습니다 :
>>> from iteration_utilities import grouper
>>> list(grouper([1, 2, 3], 2)) # as single
[(1, 2), (3,)]
>>> list(grouper([1, 2, 3], 2, truncate=True)) # ignored
[(1, 2)]
>>> list(grouper([1, 2, 3], 2, fillvalue=None)) # padded
[(1, 2), (3, None)]
zip
및 iter
명령을 함께 사용하십시오 .
이 솔루션을 사용 iter
하여 매우 우아하다고 생각합니다.
it = iter(l)
list(zip(it, it))
# [(1, 2), (3, 4), (5, 6)]
파이썬 3 zip 문서 에서 찾은 것입니다 .
it = iter(l)
print(*(f'{u} + {v} = {u+v}' for u, v in zip(it, it)), sep='\n')
# 1 + 2 = 3
# 3 + 4 = 7
# 5 + 6 = 11
N
한 번 에 요소 를 일반화하려면 다음을 수행하십시오.
N = 2
list(zip(*([iter(l)] * N)))
# [(1, 2), (3, 4), (5, 6)]
for (i, k) in zip(l[::2], l[1::2]):
print i, "+", k, "=", i+k
zip(*iterable)
각 iterable의 다음 요소와 함께 튜플을 반환합니다.
l[::2]
목록의 첫 번째, 세 번째, 다섯 번째 등 요소를 반환합니다. 첫 번째 콜론은 슬라이스 뒤에 숫자가 없기 때문에 슬라이스가 처음부터 시작 함을 나타내며 두 번째 콜론은 슬라이스의 '단계'를 원할 경우에만 필요합니다 '(이 경우 2).
l[1::2]
동일한 작업을 수행하지만 목록의 두 번째 요소에서 시작하므로 원래 목록 의 2, 4, 6 등을 반환 합니다.
[number::number]
구문 작동 방식을 설명하는 1입니다 . 파이썬을 자주 사용하지 않는 사람에게 도움이 됨
포장 풀기 :
l = [1,2,3,4,5,6]
while l:
i, k, *l = l
print(str(i), '+', str(k), '=', str(i+k))
누구나 도움이 될 수 있지만 여기에는 비슷한 문제이지만 겹치는 쌍 (상호 배타적 쌍 대신)이있는 해결책이 있습니다.
파이썬 itertools 문서에서 :
from itertools import izip
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = tee(iterable)
next(b, None)
return izip(a, b)
또는 더 일반적으로 :
from itertools import izip
def groupwise(iterable, n=2):
"s -> (s0,s1,...,sn-1), (s1,s2,...,sn), (s2,s3,...,sn+1), ..."
t = tee(iterable, n)
for i in range(1, n):
for j in range(0, i):
next(t[i], None)
return izip(*t)
more_itertools 패키지 를 사용할 수 있습니다 .
import more_itertools
lst = range(1, 7)
for i, j in more_itertools.chunked(lst, 2):
print(f'{i} + {j} = {i+j}')
간단한 접근 방식 :
[(a[i],a[i+1]) for i in range(0,len(a),2)]
이것은 배열이 a이고 쌍으로 반복하려는 경우 유용합니다. 트리플렛 이상에서 반복하려면 "range"단계 명령을 변경하십시오. 예를 들면 다음과 같습니다.
[(a[i],a[i+1],a[i+2]) for i in range(0,len(a),3)]
(배열 길이와 단계가 맞지 않으면 초과 값을 처리해야합니다)
여기에 alt_elem
for 루프에 맞는 방법을 사용할 수 있습니다.
def alt_elem(list, index=2):
for i, elem in enumerate(list, start=1):
if not i % index:
yield tuple(list[i-index:i])
a = range(10)
for index in [2, 3, 4]:
print("With index: {0}".format(index))
for i in alt_elem(a, index):
print(i)
산출:
With index: 2
(0, 1)
(2, 3)
(4, 5)
(6, 7)
(8, 9)
With index: 3
(0, 1, 2)
(3, 4, 5)
(6, 7, 8)
With index: 4
(0, 1, 2, 3)
(4, 5, 6, 7)
참고 : 위의 솔루션은 기능에서 수행되는 작업을 고려할 때 효율적이지 않을 수 있습니다.