web-dev-qa-db-ja.com

Pythonでリストの2つのリストを圧縮する方法は?

同数のアイテムを持つリストのリストが2つあります。 2つのリストは次のようになります。

_L1 = [[1, 2], [3, 4], [5, 6]]

L2 =[[a, b], [c, d], [e, f]]
_

次のようなリストを1つ作成しようとしています。

_Lmerge = [[1, 2, a, b], [3, 4, c, d], [5, 6, e, f]]
_

Zip()を次のように使用しようとしました。

_for list1, list2 in Zip(*L1, *L2):
    Lmerge = [list1, list2]
_

リストの2つのリストを組み合わせる最良の方法は何ですか?前もって感謝します。

21
drbunsen
>>> map(list.__add__, L1, L2)
[[1, 2, 'a', 'b'], [3, 4, 'c', 'd'], [5, 6, 'e', 'f']]
21
hammar
_>>> L1 = [[1, 2], [3, 4], [5, 6]]
>>> L2 =[["a", "b"], ["c", "d"], ["e", "f"]]
>>> [x + y for x,y in Zip(L1,L2)]
[[1, 2, 'a', 'b'], [3, 4, 'c', 'd'], [5, 6, 'e', 'f']]
_

または、

_>>> [sum(x,[]) for x in Zip(L1,L2)]
[[1, 2, 'a', 'b'], [3, 4, 'c', 'd'], [5, 6, 'e', 'f']]
_

または、

_>>> import itertools
>>> [list(itertools.chain(*x)) for x in Zip(L1,L2)]
[[1, 2, 'a', 'b'], [3, 4, 'c', 'd'], [5, 6, 'e', 'f']]
_

Zip()なしでも実行できます。

_>>> [L1[i] + L2[i] for i in xrange(min(len(L1), len(L2)))]  
[[1, 2, 'a', 'b'], [3, 4, 'c', 'd'], [5, 6, 'e', 'f']]

>>> [x + L2[i] for i, x in enumerate(L1)]  # assuming len(L1) == len(l2)
[[1, 2, 'a', 'b'], [3, 4, 'c', 'd'], [5, 6, 'e', 'f']]

>>> # same as above, but deals with different lengths
>>> Lx, Ly = ((L2,L1), (L1,L2))[len(L1)<=len(L2)] # shortcut for if/else
>>> [x + Ly[i] for i, x in enumerate(Lx)]
_

いくつかのベンチマーク

これまでに提供された回答のベンチマークをいくつか示します。

最も人気のある答え([x + y for x,y in Zip(L1,L2)])は @ hammarのmapソリューション とほぼ同等のようです。 一方、私が提供した代替ソリューションはごみであることが証明されています!

ただし、(今のところ)最速のソリューションは、Zip()なしでリスト内包表記を使用するソリューションのようです。

_[me@home]$ SETUP="L1=[[x,x+1] for x in xrange(10000)];L2=[[x+2,x+3] for x in xrange(10000)]"

[me@home]$ # this raises IndexError if len(L1) > len(L2)
[me@home]$ python -m timeit "$SETUP" "[x + L2[i] for i, x in enumerate(L1)]"
100 loops, best of 3: 10.6 msec per loop

[me@home]$ # same as above, but deals with length inconsistencies
[me@home]$ python -m timeit "$SETUP" "Lx,Ly=((L2,L1),(L1,L2))[len(L1)<=len(L2)];[x + Ly[i] for i, x in enumerate(Lx)]"
100 loops, best of 3: 10.6 msec per loop

[me@home]$ # almost as fast as above, but easier to read
[me@home]$ python -m timeit "$SETUP" "[L1[i] + L2[i] for i in xrange(min(len(L1),len(L2)))]"
100 loops, best of 3: 10.8 msec per loop

[me@home]$ python -m timeit "$SETUP" "L3=[x + y for x,y in Zip(L1,L2)]"
100 loops, best of 3: 13.4 msec per loop

[me@home]$ python -m timeit "$SETUP" "L3=map(list.__add__, L1, L2)" 
100 loops, best of 3: 13.5 msec per loop

[me@home]$ python -m timeit "$SETUP" "L3=[sum(x,[]) for x in Zip(L1,L2)]"
100 loops, best of 3: 18.1 msec per loop

[me@home]$ python -m timeit "$SETUP;import itertools" "L3=[list(itertools.chain(*x)) for x in Zip(L1,L2)]"
10 loops, best of 3: 32.9 msec per loop
_

@ Zacの提案 は本当に速いですが、リスト拡張インプレースを行うため、ここではリンゴとオレンジを比較しています。 )3番目のリストを作成する代わりに、_L1_に。したがって、_L1_が不要になった場合、これは優れたソリューションです。

_[me@home]$ python -m timeit "$SETUP" "for index, x in enumerate(L1): x.extend(L2[index])"
100 loops, best of 3: 9.46 msec per loop
_

ただし、_L1_をそのまま維持する必要がある場合は、ディープコピーを含めるとパフォーマンスが標準以下になります。

_[me@home]$ python -m timeit "$SETUP;from copy import deepcopy" "L3=deepcopy(L1)
> for index, x in enumerate(L1): x.extend(L2[index])"
10 loops, best of 3: 116 msec per loop
_
13
Shawn Chin

サブリストをplus演算子と組み合わせて、リスト内包表記でそれらを反復処理する必要があります。

Lmerge = [i1 + i2 for i1, i2 in Zip(L1, L2)]
4
grahamstratton
L1 = [[1, 2], [3, 4], [5, 6]]
L2 =[[a, b], [c, d], [e, f]]

Lmerge = [x + y for x, y in Zip(L1, L2)]
[[1, 2, 'a', 'b'], [3, 4, 'c', 'd'], [5, 6, 'e', 'f']]
1
STH
for index, x in enumerate(L1):
    x.extend(L2[index])
1
Zac Smith