순진한 접근
def transpose_finite_iterable(iterable):
return zip(*iterable) # `itertools.izip` for Python 2 users
다음과 같이 설명 할 수있는 (잠재적으로 무한한) 반복 가능한 유한 반복 가능한 (예 : list
/ tuple
/ str
) 시퀀스에 대해 잘 작동합니다.
| |a_00| |a_10| ... |a_n0| |
| |a_01| |a_11| ... |a_n1| |
| |... | |... | ... |... | |
| |a_0i| |a_1i| ... |a_ni| |
| |... | |... | ... |... | |
어디
n in ℕ
,
a_ij
iterable의 -th j
요소에 해당합니다 i
.
신청 후 transpose_finite_iterable
우리는 얻을
| |a_00| |a_01| ... |a_0i| ... |
| |a_10| |a_11| ... |a_1i| ... |
| |... | |... | ... |... | ... |
| |a_n0| |a_n1| ... |a_ni| ... |
이러한 경우 파이썬 예 여기서 a_ij == j
,n == 2
>>> from itertools import count
>>> iterable = [count(), count()]
>>> result = transpose_finite_iterable(iterable)
>>> next(result)
(0, 0)
>>> next(result)
(1, 1)
그러나 우리는 유한 iterables의 무한 iterable ( 우리의 경우 s) 이기 때문에 transpose_finite_iterable
원래의 구조로 돌아 가기 위해 다시 사용할 수 없습니다 :iterable
result
tuple
>>> transpose_finite_iterable(result)
... hangs ...
Traceback (most recent call last):
File "...", line 1, in ...
File "...", line 2, in transpose_finite_iterable
MemoryError
이 사건을 어떻게 다룰 수 있을까요?
... 그리고 여기에 온다 deque
우리는 docs of itertools.tee
function을 살펴본 후 약간의 수정으로 우리의 경우에 도움이 될 수있는 Python 레시피가 있습니다.
def transpose_finite_iterables(iterable):
iterator = iter(iterable)
try:
first_elements = next(iterator)
except StopIteration:
return ()
queues = [deque([element])
for element in first_elements]
def coordinate(queue):
while True:
if not queue:
try:
elements = next(iterator)
except StopIteration:
return
for sub_queue, element in zip(queues, elements):
sub_queue.append(element)
yield queue.popleft()
return tuple(map(coordinate, queues))
점검 해보자
>>> from itertools import count
>>> iterable = [count(), count()]
>>> result = transpose_finite_iterables(transpose_finite_iterable(iterable))
>>> result
(<generator object transpose_finite_iterables.<locals>.coordinate at ...>, <generator object transpose_finite_iterables.<locals>.coordinate at ...>)
>>> next(result[0])
0
>>> next(result[0])
1
합성
이제 우리는 한정되어있는 반복 가능 객체 것들의 반복 가능 객체 작업을위한 일반 함수를 정의 할 수 있으며 다른 사람이 사용하여 잠재적으로 무한 functools.singledispatch
장식을 같이
from collections import (abc,
deque)
from functools import singledispatch
@singledispatch
def transpose(object_):
"""
Transposes given object.
"""
raise TypeError('Unsupported object type: {type}.'
.format(type=type))
@transpose.register(abc.Iterable)
def transpose_finite_iterables(object_):
"""
Transposes given iterable of finite iterables.
"""
iterator = iter(object_)
try:
first_elements = next(iterator)
except StopIteration:
return ()
queues = [deque([element])
for element in first_elements]
def coordinate(queue):
while True:
if not queue:
try:
elements = next(iterator)
except StopIteration:
return
for sub_queue, element in zip(queues, elements):
sub_queue.append(element)
yield queue.popleft()
return tuple(map(coordinate, queues))
def transpose_finite_iterable(object_):
"""
Transposes given finite iterable of iterables.
"""
yield from zip(*object_)
try:
transpose.register(abc.Collection, transpose_finite_iterable)
except AttributeError:
# Python3.5-
transpose.register(abc.Mapping, transpose_finite_iterable)
transpose.register(abc.Sequence, transpose_finite_iterable)
transpose.register(abc.Set, transpose_finite_iterable)
유한 한 비어 있지 않은 이터 러블에 대한 이진 연산자의 클래스에서 자체 역수 (수학자들은 이런 종류의 함수를 " 진화 "라고 부름)로 간주 할 수 있습니다 .
singledispatch
ing 의 보너스로 다음 numpy
과 같은 배열 을 처리 할 수 있습니다.
import numpy as np
...
transpose.register(np.ndarray, np.transpose)
그런 다음 사용하십시오
>>> array = np.arange(4).reshape((2,2))
>>> array
array([[0, 1],
[2, 3]])
>>> transpose(array)
array([[0, 2],
[1, 3]])
노트
때문에 transpose
누군가가 가지고 싶어하는 경우 반환 반복자와 tuple
의 list
영업 이익처럼들 -이 함께 추가로 만들 수 있습니다 map
내장 된 기능 과 같은
>>> original = [('a', 1), ('b', 2), ('c', 3), ('d', 4)]
>>> tuple(map(list, transpose(original)))
(['a', 'b', 'c', 'd'], [1, 2, 3, 4])
광고
나는에 일반화 된 솔루션을 추가 한 lz
패키지 에서 0.5.0
처럼 사용할 수있는 버전
>>> from lz.transposition import transpose
>>> list(map(tuple, transpose(zip(range(10), range(10, 20)))))
[(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), (10, 11, 12, 13, 14, 15, 16, 17, 18, 19)]
추신
잠재적으로 무한 반복 가능한 무한 반복을 처리하는 솔루션은 (적어도 명백한) 없지만,이 경우는 덜 일반적입니다.