Pythonで2つのリストを連結するにはどうすればよいですか?

2009-11-12 python list concatenation

Pythonで2つのリストを連結するにはどうすればよいですか?

例:

listone = [1, 2, 3]
listtwo = [4, 5, 6]

期待される結果:

>>> joinedlist
[1, 2, 3, 4, 5, 6]

Answers

+演算子を使用して、それらを組み合わせることができます。

listone = [1,2,3]
listtwo = [4,5,6]

joinedlist = listone + listtwo

出力:

>>> joinedlist
[1,2,3,4,5,6]

これは非常に単純で、チュートリアルにも示されていると思います。

>>> listone = [1,2,3]
>>> listtwo = [4,5,6]
>>>
>>> listone + listtwo
[1, 2, 3, 4, 5, 6]

itertools.chain()を使用して両方のリストの項目を単純に反復するジェネレーターを作成することもできます。これにより、アイテムを新しいリストにコピーせずに、リスト(または反復可能なもの)をチェーンして処理することができます。

import itertools
for item in itertools.chain(listone, listtwo):
    # Do something with each list item

セットを使用して、一意の値のマージされたリストを取得できます

mergedlist = list(set(listone + listtwo))

list.extend()メソッドを使用して、別のlistの最後にlistを追加することもできます。

listone = [1,2,3]
listtwo = [4,5,6]

listone.extend(listtwo)

元のリストをそのまま維持したい場合は、新しいlistオブジェクトを作成し、両方のリストをそれにextendできます。

mergedlist = []
mergedlist.extend(listone)
mergedlist.extend(listtwo)

itertools.chain関数が可変数の引数を受け入れることは注目に値します。

>>> l1 = ['a']; l2 = ['b', 'c']; l3 = ['d', 'e', 'f']
>>> [i for i in itertools.chain(l1, l2)]
['a', 'b', 'c']
>>> [i for i in itertools.chain(l1, l2, l3)]
['a', 'b', 'c', 'd', 'e', 'f']

from_iterable (タプル、リスト、ジェネレーターなど)が入力の場合、 from_iterableクラスメソッドを使用できます。

>>> il = [['a'], ['b', 'c'], ['d', 'e', 'f']]
>>> [i for i in itertools.chain.from_iterable(il)]
['a', 'b', 'c', 'd', 'e', 'f']

+または+=演算子を次のように使用するだけです。

a = [1, 2, 3]
b = [4, 5, 6]

c = a + b

または:

c = []
a = [1, 2, 3]
b = [4, 5, 6]

c += (a + b)

また、マージされたリストの値を一意にしたい場合は、次のようにすることができます。

c = list(set(a + b))

listオブジェクトで定義されたappend()メソッドを使用できます。

mergedlist =[]
for elem in listone:
    mergedlist.append(elem)
for elem in listtwo:
    mergedlist.append(elem)

複雑な並べ替えルールで2つの順序付きリストをマージする必要がある場合は、次のコードのように自分でロールしなければならない場合があります(読みやすいように単純な並べ替えルールを使用する:-))。

list1 = [1,2,5]
list2 = [2,3,4]
newlist = []

while list1 and list2:
    if list1[0] == list2[0]:
        newlist.append(list1.pop(0))
        list2.pop(0)
    elif list1[0] < list2[0]:
        newlist.append(list1.pop(0))
    else:
        newlist.append(list2.pop(0))

if list1:
    newlist.extend(list1)
if list2:
    newlist.extend(list2)

assert(newlist == [1, 2, 3, 4, 5])

Python 3.3以降では、 yield fromを使用できます。

listone = [1,2,3]
listtwo = [4,5,6]

def merge(l1, l2):
    yield from l1
    yield from l2

>>> list(merge(listone, listtwo))
[1, 2, 3, 4, 5, 6]

または、任意の数のイテレータをサポートする場合:

def merge(*iters):
    for it in iters:
        yield from it

>>> list(merge(listone, listtwo, 'abcd', [20, 21, 22]))
[1, 2, 3, 4, 5, 6, 'a', 'b', 'c', 'd', 20, 21, 22]

プラス演算子( + )を使用できない場合は、 operator importを使用できます。

import operator

listone = [1,2,3]
listtwo = [4,5,6]

result = operator.add(listone, listtwo)
print(result)

>>> [1, 2, 3, 4, 5, 6]

または、 __add__ add__ dunder関数を使用することもできます。

listone = [1,2,3]
listtwo = [4,5,6]

result = list.__add__(listone, listtwo)
print(result)

>>> [1, 2, 3, 4, 5, 6]

より多くのリストのより一般的な方法として、リスト内にリストを配置し、 この回答に基づいてネストされたリストをitertools.chain.from_iterable()化するitertools.chain.from_iterable()方法であるitertools.chain.from_iterable() 1関数を使用できます。

>>> l=[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> import itertools
>>> list(itertools.chain.from_iterable(l))
[1, 2, 3, 4, 5, 6, 7, 8, 9]

1. chain.from_iterable()はPython 2.6以降で使用できることに注意してください。他のバージョンでは、 chain(*l)使用します。

2つのリストをソートされた形式でmerge場合は、 heapqライブラリのmerge機能を使用できます。

from heapq import merge

a = [1, 2, 4]
b = [2, 4, 6, 7]

print list(merge(a, b))

この質問は、2つのリストの結合について直接尋ねます。ただし、多くのリストを結合する方法を探している場合でも、検索数はかなり高くなります(リストを結合しない場合を含む)。

私は最良のオプションはリスト内包表記を使用することだと思います:

>>> a = [[1,2,3], [4,5,6], [7,8,9]]
>>> [x for xs in a for x in xs]
[1, 2, 3, 4, 5, 6, 7, 8, 9]

ジェネレータも作成できます。

>>> map(str, (x for xs in a for x in xs))
['1', '2', '3', '4', '5', '6', '7', '8', '9']

古い答え

このより一般的なアプローチを検討してください:

a = [[1,2,3], [4,5,6], [7,8,9]]
reduce(lambda c, x: c + x, a, [])

出力されます:

[1, 2, 3, 4, 5, 6, 7, 8, 9]

これは、 a[]または[[1,2,3]]場合にも正しく機能することに注意してください。

ただし、これはitertoolsより効率的に行うことができます。

a = [[1,2,3], [4,5,6], [7,8,9]]
list(itertools.chain(*a))

listが必要ないが、反復可能である場合は、 list()省略しlist()

更新

コメントでパトリック・コリンズが提案した代替案もあなたのために働くかもしれません:

sum(a, [])

すでに多くの人が指摘しているように、両方のリストにまったく同じ処理を適用する必要がある場合はitertools.chain()itertools.chain()ています。私の場合、リストとフラグが異なるラベルとフラグがあったので、もう少し複雑なものが必要でした。 itertools.chain() 、舞台裏でitertools.chain()単に次のことを行います。

for it in iterables:
    for element in it:
        yield element

https://docs.python.org/2/library/itertools.htmlを参照)、ここからインスピレーションを得て、これらの行に沿って何かを書きました:

for iterable, header, flag in ( (newList, 'New', ''), (modList, 'Modified', '-f')):
    print header + ':'
    for path in iterable:
        [...]
        command = 'cp -r' if os.path.isdir(srcPath) else 'cp'
        print >> SCRIPT , command, flag, srcPath, mergedDirPath
        [...]

ここで理解しておくべき重要な点は、リストは反復可能な特殊なケースにすぎず、他のオブジェクトと同様です。そして、Pythonのfor ... inループはタプル変数を処理できるため、複数の変数を同時にループするのは簡単です。

Python >= 3.5代替: [*l1, *l2]

言及に値するPEP 448の承認により、別の代替案が導入されました。

追加のアンパックの一般化 」というタイトルのPEPは、Pythonでstarred *式を使用するときの一般的な構文上の制限を軽減しました。これにより、2つのリスト(イテラブルすべてに適用)の結合も次のように実行できます。

>>> l1 = [1, 2, 3]
>>> l2 = [4, 5, 6]
>>> joined_list = [*l1, *l2]  # unpack both iterables in a list literal
>>> print(joined_list)
[1, 2, 3, 4, 5, 6]

この機能はPython 3.5定義されたもので、 3.xファミリの以前のバージョンにバックポートされていません。サポートされていないバージョンでは、 SyntaxErrorが発生します。

他のアプローチと同様に、これも対応するリストの要素の浅いコピーとして作成されます。


このアプローチの利点は、あなたが本当に、それを実行するために、反復可能で行いますで何かをリストを必要としないことです。 PEPで述べられているように:

これは、イテラブルを合計してより読みやすい方法としても役立ちます。 my_list + list(my_tuple) + list(my_range)などのmy_list + list(my_tuple) + list(my_range)なりました [*my_list, *my_tuple, *my_range]

したがって、 +を追加すると、型の不一致が原因でTypeErrorします。

l = [1, 2, 3]
r = range(4, 7)
res = l + r

次のことはできません:

res = [*l, *r]

これは、最初にイテラブルのコンテンツをアンパックし、次にコンテンツからlistを作成するだけだからです。

list(set(listone) | set(listtwo))

上記のコードは、順序を保持せず、各リストから重複を削除します(ただし、連結リストからは削除しません)

lst1 = [1,2]

lst2 = [3,4]

def list_combinationer(Bushisms, are_funny):

    for item in lst1:
        lst2.append(item)
        lst1n2 = sorted(lst2)
        print lst1n2

list_combinationer(lst1, lst2)

[1,2,3,4]

2つの古いリストを保持しながら新しいリストが必要な場合:

def concatenate_list(listOne, listTwo):
    joinedList = []
    for i in listOne:
        joinedList.append(i)
    for j in listTwo:
        joinedList.append(j)

    sorted(joinedList)

    return joinedList
import itertools

A = list(zip([1,3,5,7,9],[2,4,6,8,10]))
B = [1,3,5,7,9]+[2,4,6,8,10]
C = list(set([1,3,5,7,9] + [2,4,6,8,10]))

D = [1,3,5,7,9]
D.append([2,4,6,8,10])

E = [1,3,5,7,9]
E.extend([2,4,6,8,10])

F = []
for a in itertools.chain([1,3,5,7,9], [2,4,6,8,10]):
    F.append(a)


print ("A: " + str(A))
print ("B: " + str(B))
print ("C: " + str(C))
print ("D: " + str(D))
print ("E: " + str(E))
print ("F: " + str(F))

出力:

A: [(1, 2), (3, 4), (5, 6), (7, 8), (9, 10)]
B: [1, 3, 5, 7, 9, 2, 4, 6, 8, 10]
C: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
D: [1, 3, 5, 7, 9, [2, 4, 6, 8, 10]]
E: [1, 3, 5, 7, 9, 2, 4, 6, 8, 10]
F: [1, 3, 5, 7, 9, 2, 4, 6, 8, 10]

リストのリストを組み合わせる本当に簡潔な方法は

list_of_lists = [[1,2,3], [4,5,6], [7,8,9]]
reduce(list.__add__, list_of_lists)

それは私たちに与える

[1, 2, 3, 4, 5, 6, 7, 8, 9]

単純なリスト内包表記を使用します。

joined_list = [item for list_ in [list_one, list_two] for item in list_]

追加のアンパッキング汎化を使用する最新のアプローチのすべての利点があります。つまり、任意の数の異なる反復可能オブジェクト(たとえば、リスト、タプル、範囲、およびジェネレーター)をその方法で連結できます。これは、Python 3.5以降に限定されません。 。

Pythonでは、このコマンドで互換性のある次元の2つの配列を連結できます

numpy.concatenate([a,b])

したがって、2つの簡単な方法があります。

  1. +を使用 :提供されたリストから新しいリストを作成します

例:

In [1]: a = [1, 2, 3]

In [2]: b = [4, 5, 6]

In [3]: a + b
Out[3]: [1, 2, 3, 4, 5, 6]

In [4]: %timeit a + b
10000000 loops, best of 3: 126 ns per loop
  1. 拡張の使用 :既存のリストに新しいリストを追加します。つまり、個別のリストは作成されません。

例:

In [1]: a = [1, 2, 3]

In [2]: b = [4, 5, 6]

In [3]: %timeit a.extend(b)
10000000 loops, best of 3: 91.1 ns per loop

したがって、最も一般的な2つの方法のうち、 extendが効率的であるextendがわかります。

Pythonで2つのリストを連結するにはどうすればよいですか?

3.7以降、これらはPythonで2つ(またはそれ以上)のリストを連結するための最も一般的なstdlibメソッドです。

ここに画像の説明を入力してください

脚注

  1. 簡潔さのため、これは洗練されたソリューションです。しかし、 sumはペアごとに連結を実行します。つまり、これは メモリとしての2次演算は、各ステップに割り当てる必要があります。行う リストが大きい場合は使用しないでください。

  2. chain見る そして chain.from_iterable ドキュメントから。最初にimport itertoolsimport itertoolsする必要があります。 連結はメモリ内で線形であるため、これは、 パフォーマンスとバージョンの互換性。 chain.from_iterableは2.6で導入されました。

  3. この方法では、 追加のアンパック一般化(PEP 448)を使用しますが、 手動でそれぞれを開梱しない限り、N個のリストに一般化してください。

  4. a += ba.extend(b)は、すべての実用的な目的でほぼ同等です。 +=リストで呼び出されると、内部的に呼び出されます list.__iadd__は、最初のリストを2番目のリストで拡張します。


パフォーマンス

2リスト連結 1

ここに画像の説明を入力してください

これらの方法には大きな違いはありませんが、すべて同じ程度の複雑さ(線形)であることを考えると、それは理にかなっています。スタイルの問題を除いて、どちらか一方を優先する特別な理由はありません。

Nリスト連結

ここに画像の説明を入力してください

プロットは、 perfplotモジュールを使用して生成されています。 参考のために、コード。

1. iadd+= )およびextendメソッドはインプレースで動作するため、テストの前に毎回コピーを生成する必要があります。公平を期すために、すべてのメソッドには、左側のリストのコピー前のステップがありますが、これは無視できます。


他のソリューションに関するコメント

  • DUNDER METHOD list.__add__使用しないでlist.__add__は、どのような形、形、形式でも直接使用してください。実際、dunderメソッドには近づかないで、演算子とoperator関数を、それらが設計されているように使用してください。 Pythonは、dunderを直接呼び出すよりも複雑な、これらに組み込まれた慎重なセマンティクスを備えています。 例を示します。要約すると、 a.__add__(b) => BAD; a + b =>良い。

  • ここでのいくつかの回答は、ペアワイズ連結のreduce(operator.add, [a, b])を提供します-これは、 sum([a, b], [])と同じですが、より冗長です。

  • setを使用するメソッドは、重複を削除し、順序を失います。注意して使用してください。

  • for i in b: a.append(i)はよりa.extend(b)a.extend(b)よりも低速です。これは単一の関数呼び出しであり、より慣用的です。リスト用にメモリが割り当てられ、拡張されるセマンティクスのため、 appendは遅くなります。同様の議論についてはこちらをご覧ください。

  • heapq.mergeは機能しますが、そのユースケースは、ソートされたリストを線形時間でマージするためのものです。他の状況での使用はアンチパターンです。

  • 関数からリスト要素をyieldすることは許容できる方法ですが、 chainはこれをより速く、よりよく行います(Cにはコードパスがあるため、高速です)。

  • operator.add(a, b)operator.add(a, b) a + bと同等の受け入れ可能な関数です。ユースケースは主に動的メソッドのディスパッチです。そうでなければ、 私の意見では、短くて読みやすいa + bを好む。 YMMV。

Pythonでリストを連結する方法は複数あります。

l1 = [1,2,3,4]
l2 = [3,4,5,6]

1. new_list = l1.extend(l2)
2. new_list = l1 + l2
3. new_list = [*l1, *l2]

あなたはコードに従うことができます

listone = [1, 2, 3]
listtwo = [4, 5, 6]

for i in listone:
    listtwo.append(i)
print(listtwo)

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

Related