이터 러블을 일정한 크기의 청크로 분할하는 방법
중복 가능성 :
Python에서 목록을 균등 한 크기의 청크로 어떻게 분할합니까?
이터 러블을 입력으로 받아 이터 러블의 이터 러블을 반환하는 "배치"함수를 찾을 수 없다는 것에 놀랐습니다.
예를 들면 :
for i in batch(range(0,10), 1): print i
[0]
[1]
...
[9]
또는:
for i in batch(range(0,10), 3): print i
[0,1,2]
[3,4,5]
[6,7,8]
[9]
이제 저는 매우 간단한 생성기라고 생각한 것을 작성했습니다.
def batch(iterable, n = 1):
current_batch = []
for item in iterable:
current_batch.append(item)
if len(current_batch) == n:
yield current_batch
current_batch = []
if current_batch:
yield current_batch
그러나 위의 내용은 내가 기대했던 것을 제공하지 않습니다.
for x in batch(range(0,10),3): print x
[0]
[0, 1]
[0, 1, 2]
[3]
[3, 4]
[3, 4, 5]
[6]
[6, 7]
[6, 7, 8]
[9]
그래서 나는 무언가를 놓 쳤고 이것은 아마도 파이썬 생성기에 대한 나의 완전한 이해 부족을 보여줄 것입니다. 누구든지 나를 올바른 방향으로 안내해 줄 수 있습니까?
[편집 : 결국 위의 동작은 파이썬 자체가 아닌 ipython 내에서 실행할 때만 발생한다는 것을 깨달았습니다.]
이것은 아마도 더 효율적일 것입니다 (더 빠름).
def batch(iterable, n=1):
l = len(iterable)
for ndx in range(0, l, n):
yield iterable[ndx:min(ndx + n, l)]
for x in batch(range(0, 10), 3):
print x
새 목록 작성을 피합니다.
FWIW, itertools 모듈 의 레시피 는 다음 예제를 제공합니다.
def grouper(n, iterable, fillvalue=None):
"grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
args = [iter(iterable)] * n
return izip_longest(fillvalue=fillvalue, *args)
다음과 같이 작동합니다.
>>> list(grouper(3, range(10)))
[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, None, None)]
다른 사람들이 언급했듯이 귀하가 제공 한 코드는 귀하가 원하는 것을 정확히 수행합니다. 사용하는 다른 접근 방식 의 경우 다음 레시피 itertools.islice의 예 를 볼 수 있습니다 .
from itertools import islice, chain
def batch(iterable, size):
sourceiter = iter(iterable)
while True:
batchiter = islice(sourceiter, size)
yield chain([batchiter.next()], batchiter)
이상하다, Python 2.x에서 잘 작동하는 것 같습니다.
>>> def batch(iterable, n = 1):
... current_batch = []
... for item in iterable:
... current_batch.append(item)
... if len(current_batch) == n:
... yield current_batch
... current_batch = []
... if current_batch:
... yield current_batch
...
>>> for x in batch(range(0, 10), 3):
... print x
...
[0, 1, 2]
[3, 4, 5]
[6, 7, 8]
[9]
이것은 내 프로젝트에서 사용하는 것입니다. 가능한 한 효율적으로 반복 가능 또는 목록을 처리합니다.
def chunker(iterable, size):
if not hasattr(iterable, "__len__"):
# generators don't have len, so fall back to slower
# method that works with generators
for chunk in chunker_gen(iterable, size):
yield chunk
return
it = iter(iterable)
for i in range(0, len(iterable), size):
yield [k for k in islice(it, size)]
def chunker_gen(generator, size):
iterator = iter(generator)
for first in iterator:
def chunk():
yield first
for more in islice(iterator, size - 1):
yield more
yield [k for k in chunk()]
다음은 reduce함수를 사용하는 접근 방식 입니다.
짧막 한 농담:
from functools import reduce
reduce(lambda cumulator,item: cumulator[-1].append(item) or cumulator if len(cumulator[-1]) < batch_size else cumulator + [[item]], input_array, [[]])
또는 더 읽기 쉬운 버전 :
from functools import reduce
def batch(input_list, batch_size):
def reducer(cumulator, item):
if len(cumulator[-1]) < batch_size:
cumulator[-1].append(item)
return cumulator
else:
cumulator.append([item])
return cumulator
return reduce(reducer, input_list, [[]])
테스트:
>>> batch([1,2,3,4,5,6,7], 3)
[[1, 2, 3], [4, 5, 6], [7]]
>>> batch(a, 8)
[[1, 2, 3, 4, 5, 6, 7]]
>>> batch([1,2,3,None,4], 3)
[[1, 2, 3], [None, 4]]
한 가지 대답을 했어요. 그러나 이제는 새로운 기능을 작성하지 않는 것이 최선의 해결책이라고 생각합니다. More-itertools 에는 많은 추가 도구가 포함되어 chunked있으며 그 중 하나입니다.
이것은 iterable에 대해 작동합니다.
from itertools import zip_longest, filterfalse
def batch_iterable(iterable, batch_size=2):
args = [iter(iterable)] * batch_size
return (tuple(filterfalse(lambda x: x is None, group)) for group in zip_longest(fillvalue=None, *args))
다음과 같이 작동합니다.
>>>list(batch_iterable(range(0,5)), 2)
[(0, 1), (2, 3), (4,)]
PS: It would not work if iterable has None values.
This is a very short code snippet I know (not my creation) that does not use len and works under both Python 2 and 3 (not my creation):
def chunks(iterable, size):
from itertools import chain, islice
iterator = iter(iterable)
for first in iterator:
yield list(chain([first], islice(iterator, size - 1)))
def batch(iterable, n):
iterable=iter(iterable)
while True:
chunk=[]
for i in range(n):
try:
chunk.append(next(iterable))
except StopIteration:
yield chunk
return
yield chunk
list(batch(range(10), 3))
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]
참고URL : https://stackoverflow.com/questions/8290397/how-to-split-an-iterable-in-constant-size-chunks
'Program Club' 카테고리의 다른 글
| AJAX 도메인 간 호출 (0) | 2020.11.17 |
|---|---|
| Java에서 Comparable.compareTo의 반환 값은 무엇을 의미합니까? (0) | 2020.11.16 |
| WinRT의 UI 스레드에서 코드 실행 (0) | 2020.11.16 |
| Python은 키 목록이 사전에 있는지 확인합니다. (0) | 2020.11.16 |
| jQuery promise를 사용하여 3 개의 비동기 호출을 어떻게 연결합니까? (0) | 2020.11.16 |