2 개의 항목 튜플 목록이 있고 첫 번째 항목은 각 튜플의 첫 번째 항목을 포함하고 두 번째 목록은 두 번째 항목을 포함하는 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 ])
그것은 해야 더 확장 할 수 있습니다. 특히 파이썬이 필요하지 않으면 목록 이해력을 확장하지 않는 것이 좋습니다.
(우연히, 튜플 목록이 아닌 2 튜플 (쌍) 목록을 zip
만듭니다.)
실제 목록 대신 생성기가 괜찮다면 다음과 같이하십시오.
result = (( a for a,b in original ), ( b for a,b in original ))
생성기는 각 요소를 요청할 때까지 목록을 검색하지 않지만 원래 목록을 계속 참조합니다.
답변
길이가 다른 목록이있는 경우 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으로 채울 수 있습니다.
>>> map(None, *[('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', )])
[('a', 'b', 'c', 'd', 'e'), (1, 2, 3, 4, None)]
zip ()은 약간 빠릅니다.
답변
나는 zip(*iterable)
내 프로그램에서 (당신이 찾고있는 코드 조각)을 다음 과 같이 사용 하고 싶다.
def unzip(iterable):
return zip(*iterable)
내가 찾아 unzip
더 읽기.
답변
>>> 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)]
두 목록의 압축을 풉니 다.
답변
순진한 접근
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의 -thj
요소에 해당합니다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)]
추신
잠재적으로 무한 반복 가능한 무한 반복을 처리하는 솔루션은 (적어도 명백한) 없지만,이 경우는 덜 일반적입니다.
답변
그것을하는 또 다른 방법 일뿐이지만 여기에 많은 도움이되었습니다.
이 데이터 구조를 가지고 :
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')]
압축을 풀고 원본으로 돌아가는 더 pythonic 방법은 내 의견으로는 다음과 같습니다.
x,y=zip(*XY)
그러나 이것은 튜플을 반환하므로 목록이 필요하면 다음을 사용할 수 있습니다.
x,y=(list(x),list(y))