파이썬에서 길이가 같은 두 목록을 인터리브하는 좋은 방법이 있습니까?
I 'm given [1,2,3]and [10,20,30]. 나는 그것들을 [1,10,2,20,3,30].
답변:
질문을 게시 한 후 다음을 수행 할 수 있다는 것을 깨달았습니다.
[val for pair in zip(l1, l2) for val in pair]
경우 l1와 l2두 목록입니다.
인터리브 할 N 개의 목록이있는 경우
lists = [l1, l2, ...]
[val for tup in zip(*lists) for val in tup]
izip_longestpython2 및 zip_longestpython3` [val for pair in itertools.zip_longest(l1, l2) for val in pair]결과에 사용하십시오.['a', 'b', 'a', 'b', 'a', 'b', None, 'b', None, 'b', None, 'b']
Python> = 2.3의 경우 확장 된 슬라이스 구문이 있습니다 .
>>> a = [0, 2, 4, 6, 8]
>>> b = [1, 3, 5, 7, 9]
>>> c = a + b
>>> c[::2] = a
>>> c[1::2] = b
>>> c
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
줄 c = a + b은 정확한 길이의 새 목록을 만드는 간단한 방법으로 사용됩니다 (이 단계에서는 내용이 중요하지 않음). 다음 두 줄은 인터리빙의 실제 작업 수행 a과 b: 첫 번째는 요소에 할당 a된 모든 짝수 인덱스에를 c; 두 번째는의 b모든 홀수 인덱스에 의 요소를 할당합니다 c.
주어진
a = [1, 2, 3]
b = [10, 20, 30]
c = [100, 200, 300, 999]
암호
길이가 같은 목록을 가정하면 itertools.chain및 zip다음을 사용 하여 인터리브 된 목록을 얻을 수 있습니다 .
import itertools
list(itertools.chain(*zip(a, b)))
# [1, 10, 2, 20, 3, 30]
대안
일반적으로 같지 않은 목록의 경우 다음을 사용하십시오 zip_longest(권장).
[x for x in itertools.chain(*itertools.zip_longest(a, c)) if x is not None]
# [1, 100, 2, 200, 3, 300, 999]
많은 목록을 안전하게 인터리브 할 수 있습니다.
[x for x in itertools.chain(*itertools.zip_longest(a, b, c)) if x is not None]
# [1, 10, 100, 2, 20, 200, 3, 30, 300, 999]
roundrobinitertools 레시피 와 함께 제공되는 라이브러리 interleave및 interleave_longest.
import more_itertools
list(more_itertools.roundrobin(a, b))
# [1, 10, 2, 20, 3, 30]
list(more_itertools.interleave(a, b))
# [1, 10, 2, 20, 3, 30]
list(more_itertools.interleave_longest(a, c))
# [1, 100, 2, 200, 3, 300, 999]
yield from
마지막으로 Python 3에서 흥미로운 점 (권장되지는 않음) :
list(filter(None, ((yield from x) for x in zip(a, b))))
# [1, 10, 2, 20, 3, 30]
list([(yield from x) for x in zip(a, b)])
# [1, 10, 2, 20, 3, 30]
+ 사용하여 설치pip install more_itertools
나는 수용된 대답이 다루지 않는 다른 크기의 목록으로 이것을 수행하는 방법이 필요했습니다.
내 솔루션은 생성기를 사용하고 그 사용은 그 때문에 약간 더 좋아 보입니다.
def interleave(l1, l2):
iter1 = iter(l1)
iter2 = iter(l2)
while True:
try:
if iter1 is not None:
yield next(iter1)
except StopIteration:
iter1 = None
try:
if iter2 is not None:
yield next(iter2)
except StopIteration:
iter2 = None
if iter1 is None and iter2 is None:
raise StopIteration()
그리고 그 사용법 :
>>> a = [1, 2, 3, 4, 5]
>>> b = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> list(interleave(a, b))
[1, 'a', 2, 'b', 3, 'c', 4, 'd', 5, 'e', 'f', 'g']
>>> list(interleave(b, a))
['a', 1, 'b', 2, 'c', 3, 'd', 4, 'e', 5, 'f', 'g']
roundrobin레시피itertools 는 이것의보다 일반적인 확장입니다.
대안 :
>>> l1=[1,2,3]
>>> l2=[10,20,30]
>>> [y for x in map(None,l1,l2) for y in x if y is not None]
[1, 10, 2, 20, 3, 30]
이것은 지도 가 목록에서 병렬로 작동하기 때문에 작동합니다. 그것은 동일하게 작동 2.2에서. 자체적 None으로 호출 된 함수 map로 튜플 목록을 생성합니다.
>>> map(None,l1,l2,'abcd')
[(1, 10, 'a'), (2, 20, 'b'), (3, 30, 'c'), (None, None, 'd')]
그런 다음 튜플 목록을 평면화하십시오.
물론 장점 map 은 목록의 수에 관계없이 작동하며 길이가 다른 경우에도 작동한다는 것입니다.
>>> l1=[1,2,3]
>>> l2=[10,20,30]
>>> l3=[101,102,103,104]
>>> [y for x in map(None,l1,l2,l3) for y in x if y in not None]
[1, 10, 101, 2, 20, 102, 3, 30, 103, 104]
if y걸러 0도 if y is not None덜 취약하다.
나는 aix의 솔루션을 가장 좋아합니다. 2.2에서 작동해야한다고 생각하는 또 다른 방법이 있습니다.
>>> x=range(3)
>>> x
[0, 1, 2]
>>> y=range(7,10)
>>> y
[7, 8, 9]
>>> sum(zip(x,y),[])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate list (not "tuple") to list
>>> sum(map(list,zip(x,y)),[])
[0, 7, 1, 8, 2, 9]
한 가지 더 방법 :
>>> a=[x,y]
>>> [a[i][j] for j in range(3) for i in (0,1)]
[0, 7, 1, 8, 2, 9]
과:
>>> sum((list(i) for i in zip(x,y)),[])
[0, 7, 1, 8, 2, 9]
[el for el in itertools.chain(*itertools.izip_longest([1,2,3], [4,5])) if el is not None]
당신이없는만큼 None유지하려는 것을
"Python에서 동일한 길이의 여러 목록을 인터리브"라는 질문 제목에 답하기 위해 @ekhumoro의 2 개 목록 답을 일반화 할 수 있습니다. 이를 위해서는 @NPE의 (우아한) 솔루션과 달리 목록의 길이가 동일해야합니다.
import itertools
def interleave(lists):
"""Interleave a list of lists.
:param lists: List of lists; each inner length must be the same length.
:returns: interleaved single list
:rtype: list
"""
if len(set(len(_) for _ in lists)) > 1:
raise ValueError("Lists are not all the same length!")
joint = list(itertools.chain(*lists))
for l_idx, li in enumerate(lists):
joint[l_idx::len(lists)] = li
return joint
예 :
>>> interleave([[0,2,4], [1, 3, 5]])
[0, 1, 2, 3, 4, 5]
>>> interleave([[0,2,4], [1, 3, 5], [10, 11, 12]])
[0, 1, 10, 2, 3, 11, 4, 5, 12]
>>> interleave([[0,2,4], [1, 3, 5], [10, 11, 12], [13, 14, 15]])
[0, 1, 10, 13, 2, 3, 11, 14, 4, 5, 12, 15]
>>> interleave([[0,2,4], [1, 3, 5], [10, 11, 12], [13, 14]])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 10, in interleave
ValueError: Lists are not all the same length!
>>> interleave([[0,2,4]])
[0, 2, 4]
it = iter(l1); list((yield next(it)) or i for i in l2)