전치/해동 기능(zip 반대)
저는 2개의 아이템 튜플 리스트를 가지고 있는데, 각 튜플에 첫 번째 아이템이 포함된 리스트와 두 번째 아이템이 포함된 리스트로 변환하고 싶습니다.
예를 들어 다음과 같습니다.
original = [('a', 1), ('b', 2), ('c', 3), ('d', 4)]
# and I want to become...
result = (['a', 'b', 'c', 'd'], [1, 2, 3, 4])
그런 기능이 내장되어 있나요?
zip
그 자체가 반전이야!특별한 * 연산자를 사용하는 경우.
>>> zip(*[('a', 1), ('b', 2), ('c', 3), ('d', 4)])
[('a', 'b', 'c', 'd'), (1, 2, 3, 4)]
은 " " "를 호출하는 입니다.zip
다음 인수를 사용합니다.
zip(('a', 1), ('b', 2), ('c', 3), ('d', 4))
가 …에게 한다.zip
(태플로 변환된 후) 직접 생성되므로 인수의 수가 너무 커질 염려가 없습니다.
할 수도 있고
result = ([ a for a,b in original ], [ b for a,b in original ])
더 잘 확장될 거예요.특히 Python이 필요한 경우를 제외하고는 목록 통합을 확장하지 않는 것이 좋습니다.
TUPLE .를 들어, ('TUPLE'의 2태플(쌍)이 됩니다zip
실제 목록이 아닌 제너레이터가 정상인 경우 다음과 같이 됩니다.
result = (( a for a,b in original ), ( b for a,b in original ))
생성기는 사용자가 각 요소를 요청할 때까지 목록을 대충 훑어보지 않지만, 다른 한편으로는 원래 목록에 대한 참조를 유지합니다.
사용하는 것을 좋아합니다.zip(*iterable)
있는 입니다) 라고 코드의 일부를 제 과 같이 되어 있습니다
def unzip(iterable):
return zip(*iterable)
unzip
가독성이 향상됩니다.
같은 길이가 아닌 목록이 있는 경우 Patricks의 답변에 따라 zip을 사용하지 않는 것이 좋습니다.이 방법은 다음과 같습니다.
>>> zip(*[('a', 1), ('b', 2), ('c', 3), ('d', 4)])
[('a', 'b', 'c', 'd'), (1, 2, 3, 4)]
그러나 길이가 다른 목록을 사용하면 zip은 각 항목을 최단 목록 길이로 잘라냅니다.
>>> zip(*[('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', )])
[('a', 'b', 'c', 'd', 'e')]
함수가 없는 맵을 사용하여 빈 결과를 없음으로 채울 수 있습니다.
>>> map(None, *[('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', )])
[('a', 'b', 'c', 'd', 'e'), (1, 2, 3, 4, None)]
zip()이 약간 더 빠릅니다.
>>> original = [('a', 1), ('b', 2), ('c', 3), ('d', 4)]
>>> tuple([list(tup) for tup in zip(*original)])
(['a', 'b', 'c', 'd'], [1, 2, 3, 4])
질문에서와 같이 일련의 목록을 제공합니다.
list1, list2 = [list(tup) for tup in zip(*original)]
2개의 리스트를 언팩 합니다.
순진한 접근법
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
대응하다j
의i
할 수 있는 -반복하다
'이행'을 한 후transpose_finite_iterable
| |a_00| |a_01| ... |a_0i| ... |
| |a_10| |a_11| ... |a_1i| ... |
| |... | |... | ... |... | ... |
| |a_n0| |a_n1| ... |a_ni| ... |
의 Python의 로서, Python은 다음과 같습니다.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)
못 요.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
기능 문서를 살펴본 후, 약간의 수정이 우리의 경우에 도움이 될 수 있는 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
합성
이제 우리는 다음과 같은 데코레이터를 사용하여 유한하고 잠재적으로 무한인 반복 가능의 반복 가능에 대한 일반적인 함수를 정의할 수 있습니다.
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
가 수 .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
s는 OP와 같습니다.이것은, 다음과 같은 빌트인 기능을 사용해 추가 가능합니다.
>>> original = [('a', 1), ('b', 2), ('c', 3), ('d', 4)]
>>> tuple(map(list, transpose(original)))
(['a', 'b', 'c', 'd'], [1, 2, 3, 4])
광고
패키지에 범용 솔루션을 추가했습니다.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)]
추신.
(적어도) 무한 반복 가능성이 있는 무한 반복 가능성의 처리를 위한 솔루션은 없지만, 이 경우는 그다지 흔하지 않습니다.
다른 방법일 뿐이지만 많은 도움이 되었기 때문에 여기에 씁니다.
데이터 구조는 다음과 같습니다.
X=[1,2,3,4]
Y=['a','b','c','d']
XY=zip(X,Y)
결과:
In: XY
Out: [(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')]
지퍼를 내리고 원래대로 돌아가는 더 비꼬는 방법은 다음과 같습니다.
x,y=zip(*XY)
그러나 이렇게 하면 태플이 반환되므로 목록이 필요한 경우 다음을 사용할 수 있습니다.
x,y=(list(x),list(y))
more_itertools.unzip을 사용하는 것을 검토합니다.
>>> from more_itertools import unzip
>>> original = [('a', 1), ('b', 2), ('c', 3), ('d', 4)]
>>> [list(x) for x in unzip(original)]
[['a', 'b', 'c', 'd'], [1, 2, 3, 4]]
위의 답변 중 어느 것도 튜플 목록이 아닌 목록 태플인 필요한 출력을 효율적으로 제공하지 않습니다.전자의 경우,tuple
map
다음은 차이점입니다.
res1 = list(zip(*original)) # [('a', 'b', 'c', 'd'), (1, 2, 3, 4)]
res2 = tuple(map(list, zip(*original))) # (['a', 'b', 'c', 'd'], [1, 2, 3, 4])
이전 .여기서 Python 2.7은 Python 2.7입니다.zip
는 반복자가 아닌 목록을 반환합니다.
3.를 Python 3.x의 .list
★★★★★★★★★★★★★★★★★」tuple
리터레이터를 방전시킵니다.이 높은 반복기에서는 할 수 .list
★★★★★★★★★★★★★★★★★」tuple
각 솔루션에 대한 요구.
numpy 어레이와 팬더가 선호될 수 있지만, 이 기능은 다음과 같은 동작을 모방합니다.zip(*args)
라고 때unzip(args)
.
gener allows the from from from from allows 、 성 、 allows 、 allows 、 allows 、 allows allows allows 。 ★★★★★★★★★★★★★★★★★,zip
3에서는 Python 3으로 .args
이러한 가치를 통해 반복합니다.가치관을통해 반복될 때.
def unzip(items, cls=list, ocls=tuple):
"""Zip function in reverse.
:param items: Zipped-like iterable.
:type items: iterable
:param cls: Container factory. Callable that returns iterable containers,
with a callable append attribute, to store the unzipped items. Defaults
to ``list``.
:type cls: callable, optional
:param ocls: Outer container factory. Callable that returns iterable
containers. with a callable append attribute, to store the inner
containers (see ``cls``). Defaults to ``tuple``.
:type ocls: callable, optional
:returns: Unzipped items in instances returned from ``cls``, in an instance
returned from ``ocls``.
"""
# iter() will return the same iterator passed to it whenever possible.
items = iter(items)
try:
i = next(items)
except StopIteration:
return ocls()
unzipped = ocls(cls([v]) for v in i)
for i in items:
for c, v in zip(unzipped, i):
c.append(v)
return unzipped
목록 cointainers을 사용하려면, 단지 목록동인을사용하려면 단순히 실행.unzip(zipped)
, as,~하듯이
unzip(zip(["a","b","c"],[1,2,3])) == (["a","b","c"],[1,2,3])
deques, 또는 또는컨테이너 사용 스포츠용 기타 다른 어떠한 컨테이너 스포츠 데크를 사용하려면.append
, 한 공장 기능.공장출하시 기능을 통과합니다.
from collections import deque
unzip([("a",1),("b",2)], deque, list) == [deque(["a","b"]),deque([1,2])]
( 꾸미(장식)cls
및/또는 및/또는main_cls
마이크로 경영 컨테이너 초기화려면 잠시 최종다고 주장하는 성명에서 상류에 있다.)이라고 보여 주었다.위의 최종 어설션 스테이트먼트에서 간략하게 나타난 바와 같이,컨테이너초기화를 미세하게 관리합니다.
때문에 반환합니다 tuples,(메모리톤을 사용할 수 있).zip(*zipped)
트릭은 유용하기보다 영리해 보입니다.
여기 zip의 역기능이 있습니다.
def unzip(zipped):
"""Inverse of built-in zip function.
Args:
zipped: a list of tuples
Returns:
a tuple of lists
Example:
a = [1, 2, 3]
b = [4, 5, 6]
zipped = list(zip(a, b))
assert zipped == [(1, 4), (2, 5), (3, 6)]
unzipped = unzip(zipped)
assert unzipped == ([1, 2, 3], [4, 5, 6])
"""
unzipped = ()
if len(zipped) == 0:
return unzipped
dim = len(zipped[0])
for i in range(dim):
unzipped = unzipped + ([tup[i] for tup in zipped], )
return unzipped
한편, 「 」는, 「 」, 「 」의 사이에zip(*seq)
는 매우 유용하며, 전달되는 값의 태플이 생성되므로 매우 긴 시퀀스에 적합하지 않을 수 있습니다.예를 들어, 저는 100만 개 이상의 엔트리를 가진 좌표계를 이용해 직접 시퀀스를 작성하는 것이 상당히 빠르다는 것을 알게 되었습니다.
일반적인 접근방식은 다음과 같습니다.
from collections import deque
seq = ((a1, b1, …), (a2, b2, …), …)
width = len(seq[0])
output = [deque(len(seq))] * width # preallocate memory
for element in seq:
for s, item in zip(output, element):
s.append(item)
그러나 결과를 어떻게 처리하느냐에 따라 수집 선택이 크게 달라질 수 있습니다.실제 사용 사례에서는 내부 루프를 사용하지 않고 세트를 사용하는 것이 다른 모든 접근 방식보다 현저하게 빠릅니다.
그리고 다른 사람들이 지적했듯이 데이터셋을 사용하는 경우 Numpy 또는 Panda 컬렉션을 사용하는 것이 현명할 수 있습니다.
다음은 원하는 출력을 생성하는 간단한 한 줄의 답변은 다음과 같습니다.
original = [('a', 1), ('b', 2), ('c', 3), ('d', 4)]
list(zip(*original))
# [('a', 'b', 'c', 'd'), (1, 2, 3, 4)]
언급URL : https://stackoverflow.com/questions/19339/transpose-unzip-function-inverse-of-zip
'programing' 카테고리의 다른 글
MySQL에서 열 값에 문자열을 추가하는 방법 (0) | 2022.09.21 |
---|---|
파일의 첫 줄만 읽으시겠습니까? (0) | 2022.09.21 |
JUnit의 장애와 오류의 차이점은 무엇입니까? (0) | 2022.09.21 |
json과 simplejson Python 모듈의 차이점은 무엇입니까? (0) | 2022.09.21 |
PHP에서 후행 0을 제거하는 방법 (0) | 2022.09.21 |