정수 목록을 입력으로 사용하는 Python 스크립트가 있는데 한 번에 4 개의 정수로 작업해야합니다. 불행히도 입력을 제어 할 수 없거나 4 요소 튜플 목록으로 전달했습니다. 현재이 방법으로 반복하고 있습니다.
for i in xrange(0, len(ints), 4):
# dummy op for example code
foo += ints[i] * ints[i + 1] + ints[i + 2] * ints[i + 3]
“C-think”와 비슷해 보이지만,이 상황을 다루는 더 파이썬적인 방법이 있다고 생각합니다. 반복 후 목록이 삭제되므로 보존 할 필요가 없습니다. 아마도 이런 것이 더 좋을까요?
while ints:
foo += ints[0] * ints[1] + ints[2] * ints[3]
ints[0:4] = []
그래도 여전히 “느낌”이 아닙니다. :-/
관련 질문 : 파이썬에서 어떻게 목록을 고른 크기의 덩어리로 나눕니 까?
답변
파이썬 itertools 문서 의 레시피 섹션 에서 수정되었습니다 .
from itertools import zip_longest
def grouper(iterable, n, fillvalue=None):
args = [iter(iterable)] * n
return zip_longest(*args, fillvalue=fillvalue)
예제
의사 코드로 예제를 간결하게 유지합니다.
grouper('ABCDEFG', 3, 'x') --> 'ABC' 'DEF' 'Gxx'
참고 : Python 2에서는 izip_longest
대신 대신 사용하십시오 zip_longest
.
답변
def chunker(seq, size):
return (seq[pos:pos + size] for pos in range(0, len(seq), size))
# (in python 2 use xrange() instead of range() to avoid allocating a list)
단순한. 쉬운. 빠른. 모든 시퀀스에서 작동합니다.
text = "I am a very, very helpful text"
for group in chunker(text, 7):
print repr(group),
# 'I am a ' 'very, v' 'ery hel' 'pful te' 'xt'
print '|'.join(chunker(text, 10))
# I am a ver|y, very he|lpful text
animals = ['cat', 'dog', 'rabbit', 'duck', 'bird', 'cow', 'gnu', 'fish']
for group in chunker(animals, 3):
print group
# ['cat', 'dog', 'rabbit']
# ['duck', 'bird', 'cow']
# ['gnu', 'fish']
답변
나는 팬입니다
chunk_size= 4
for i in range(0, len(ints), chunk_size):
chunk = ints[i:i+chunk_size]
# process chunk of size <= chunk_size
답변
import itertools
def chunks(iterable,size):
it = iter(iterable)
chunk = tuple(itertools.islice(it,size))
while chunk:
yield chunk
chunk = tuple(itertools.islice(it,size))
# though this will throw ValueError if the length of ints
# isn't a multiple of four:
for x1,x2,x3,x4 in chunks(ints,4):
foo += x1 + x2 + x3 + x4
for chunk in chunks(ints,4):
foo += sum(chunk)
또 다른 방법:
import itertools
def chunks2(iterable,size,filler=None):
it = itertools.chain(iterable,itertools.repeat(filler,size-1))
chunk = tuple(itertools.islice(it,size))
while len(chunk) == size:
yield chunk
chunk = tuple(itertools.islice(it,size))
# x2, x3 and x4 could get the value 0 if the length is not
# a multiple of 4.
for x1,x2,x3,x4 in chunks2(ints,4,0):
foo += x1 + x2 + x3 + x4
답변
from itertools import izip_longest
def chunker(iterable, chunksize, filler):
return izip_longest(*[iter(iterable)]*chunksize, fillvalue=filler)
답변
이 문제에 대한 이상적인 솔루션은 시퀀스뿐만 아니라 반복자와도 작동합니다. 또한 빠릅니다.
itertools 문서에서 제공하는 솔루션입니다.
def grouper(n, iterable, fillvalue=None):
#"grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
args = [iter(iterable)] * n
return itertools.izip_longest(fillvalue=fillvalue, *args)
%timeit
내 Mac Book Air에서 ipython을 사용하면 루프 당 47.5 us를 얻습니다.
그러나 결과가 짝수 그룹으로 채워지기 때문에 이것은 실제로 작동하지 않습니다. 패딩이없는 솔루션은 약간 더 복잡합니다. 가장 순진한 해결책은 다음과 같습니다.
def grouper(size, iterable):
i = iter(iterable)
while True:
out = []
try:
for _ in range(size):
out.append(i.next())
except StopIteration:
yield out
break
yield out
간단하지만 꽤 느리다 : 루프 당 693 us
내가 만들 수있는 가장 좋은 해결책 islice
은 내부 루프에 대한 용도 입니다.
def grouper(size, iterable):
it = iter(iterable)
while True:
group = tuple(itertools.islice(it, None, size))
if not group:
break
yield group
동일한 데이터 세트로 루프 당 305 us를 얻습니다.
그보다 더 빠른 솔루션을 얻을 수없는 경우 다음과 같은 솔루션에 중요한 경고를 제공합니다. 입력 데이터에 인스턴스가 filldata
있는 경우 잘못된 답변을 얻을 수 있습니다.
def grouper(n, iterable, fillvalue=None):
#"grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
args = [iter(iterable)] * n
for i in itertools.izip_longest(fillvalue=fillvalue, *args):
if tuple(i)[-1] == fillvalue:
yield tuple(v for v in i if v != fillvalue)
else:
yield i
나는이 답변을 정말로 좋아하지 않지만 상당히 빠릅니다. 루프 당 124 us
답변
세트 및 생성기와 함께 작동하는 솔루션이 필요했습니다. 나는 매우 짧고 예쁜 것을 생각 해낼 수 없었지만 적어도 꽤 읽을 수 있습니다.
def chunker(seq, size):
res = []
for el in seq:
res.append(el)
if len(res) == size:
yield res
res = []
if res:
yield res
명부:
>>> list(chunker([i for i in range(10)], 3))
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]
세트:
>>> list(chunker(set([i for i in range(10)]), 3))
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]
발전기:
>>> list(chunker((i for i in range(10)), 3))
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]