Як з'єднати два списки в Python?


2527

Як з'єднати два списки в Python?

Приклад:

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

Очікуваний результат:

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

6
Ви хочете просто додати або ви хочете об'єднати два списки у відсортованому порядку ? Який вихід ви очікуєте для [1,3,6] та [2,4,5]? Чи можна припустити, що обидва підлісти вже відсортовані (як у вашому прикладі)?
smci

1
... а що робити, якщо у списках є дублікати, наприклад [1,2,5] and [2,4,5,6]? Ви хочете, щоб дублікати були включені, виключені чи не байдуже?
smci

Відповіді:


3900

Ви можете використовувати +оператор, щоб комбінувати їх:

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

joinedlist = listone + listtwo

Вихід:

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

110
це створює глибоку копію listone та додає listtwo?
Даніель Ф

152
@Daniel створить новий список з дрібною копією елементів у першому списку, а потім дрібну копію елементів у другому списку. Використовуйте copy.deepcopy, щоб отримати глибокі копії списків.
Даніель Г

219
Ще одна корисна деталь тут: listone += listtwoрезультати вlistone == [1, 2, 3, 4, 5, 6]
rickcnagy

16
@ br1ckb0t це змінить те, на що вказує listone? Отже: list3 = listone listone+=listtwo чи змінюється також list3?
Майк

11
це зміни list3. Однак, якщо це не проблема, простіше читатимо додавати два списки замість створення нового.
rickcnagy

316

Можливо також створити генератор, який просто повторює елементи в обох списках, використовуючи itertools.chain(). Це дозволяє ланцюжка списків (або будь-яких ітерабельних) разом для обробки без копіювання елементів у новий список:

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

4
chainзнаходиться на більш повільній стороні (але не набагато) для двох списків, але це найшвидше рішення для зв'язання декількох списків (n >> 2).
cs95

@ cs95 повільний порівняно з чим?
Moberg

@Moberg За порівнянні з іншими способами конкатенації списків, для довідки см моїх тестів тут .
cs95

262

>= 3.5Альтернатива Python :[*l1, *l2]

Ще одна альтернатива була введена, прийняття PEP 448якої заслуговує на згадку.

PEP під назвою " Додаткові розпаковувальні узагальнення" , як правило, зменшував деякі синтаксичні обмеження при використанні зірочного *вираження в Python; з нею тепер об'єднання двох списків (стосується будь-якого ітерабельного):

>>> 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родині. У непідтримуваних версіях A SyntaxErrorбуде піднято.

Як і в інших підходах, це теж створює дрібну копію елементів у відповідних списках.


Перевернуте цей підхід полягає в тому , що ви дійсно не потрібно списках для того , щоб виконати це, все , що ітератор буде робити. Як зазначено в ПЕП:

Це також корисно як більш читабельний спосіб підбиття ітерабелів до списку, такого, 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зі змісту.


1
Хороший приклад розпакування підходу, що працює над ітерабельними типами, - це функції, які повертають ітератор над одним із списків, які ви об'єднуєте. Наприклад, ви могли б повернути назад один зі списків ви конкатенації: res = [*l1, *reversed(l2)]. Оскільки reversedповертає ітератор, res = l1 + reversed(l2)він видасть помилку.
алан

2
Варто зазначити, що це аналогічно поєднанню словника в python. dict3 = {** dict1, ** dict2}. Зверніть увагу, що ми використовуємо ** для розпакування словника, тоді як зі списками ми використовуємо * для розпакування.
Кевін S

212

Ви можете використовувати набори для отримання об'єднаного списку унікальних значень

mergedlist = list(set(listone + listtwo))

45
Правда, проте він також видалить дублікати, якщо саме це вас цікавить. Додавання списку поряд з цим не зробить.
metasoarous

1
Який спосіб це зробити і зберегти інформацію про замовлення?
Натим

11
Краще, ніжlistone + [x for x in listtwo if x not in listone]
Натим

8
+1 IMHO - це правильний спосіб "об’єднання" (об'єднання) списків, а "схвалена" відповідь описує, як поєднувати / додавати списки (мультисети)
alfasin

2
Якщо ви дбаєте про підтримку порядку введення, тоді import collections; mergedlist = list(collections.OrderedDict.fromkeys(listone + listtwo))зробите свою справу.
SethMMorton

185

Ви також можете скористатися list.extend()методом, щоб додати a listдо кінця іншого:

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

listone.extend(listtwo)

Якщо ви хочете зберегти оригінальний список недоторканим, ви можете створити новий listоб’єкт та extendобидва списки до нього:

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

80

Як з'єднати два списки в Python?

Станом на 3.7, це найпопулярніші методи stdlib для об'єднання двох (або більше) списків у python.

введіть тут опис зображення

Виноски

  1. Це гладке рішення через його лаконічність. Але sumвиконує конкатенацію попарно, це означає, що це квадратична операція, оскільки для кожного кроку потрібно виділяти пам'ять. НЕ ВИКОРИСТОВУЙТЕ, якщо ваші списки великі.

  2. Див. chain І chain.from_iterable з док. Вам потрібно import itertoolsспочатку. Конкатенація лінійна в пам'яті, тому це найкраще з точки зору продуктивності та сумісності версій. chain.from_iterableбуло введено в 2.6.

  3. Цей метод використовує додаткові генерації розпакування (PEP 448) , але не може узагальнити до N списків, якщо ви не розпакуйте кожне вручну самостійно.

  4. a += bі a.extend(b)є більш-менш рівноцінними для всіх практичних цілей. +=при виклику в списку буде внутрішній дзвінок list.__iadd__, який розширює перший список на другий.


Продуктивність

З’єднання в 2 списку 1

введіть тут опис зображення

Різниця між цими методами не велика, але це має сенс, враховуючи, що всі вони мають однаковий порядок складності (лінійний). Немає особливих причин віддавати перевагу одному над іншим, крім питання стилю.

З'єднання N-списків

введіть тут опис зображення

Діаграми були створені за допомогою модуля perfplot . Код, для довідки.

1. iadd( +=) та extendметоди діють на місці, тому копія повинна створюватися кожного разу перед тестуванням. Щоб зробити справи справедливими, усі методи мають крок попередньої копії для лівого списку, який можна ігнорувати.


Коментарі щодо інших рішень

  • НЕ ВИКОРИСТОВУЙТЕ МЕТОДУ ДУНДЕРУ list.__add__безпосередньо ні в якому разі, формі чи формі. Насправді залишайтеся осторонь методів, а також використовуйте оператори та operatorфункції, як вони були розроблені. Python має ретельну семантику, яка є більш складною, ніж просто виклик кандидата безпосередньо. Ось приклад . Отже, підсумовуючи, 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)функція виклику однієї функції та ідіоматичніша. appendповільніше через семантику, з якою пам'ять виділяється та вирощується для списків. Дивіться тут для подібної дискусії.

  • heapq.mergeбуде працювати, але випадок його використання призначений для об'єднання відсортованих списків у лінійний час. Використання його в будь-якій іншій ситуації є анти-закономірністю.

  • yieldЯкщо список елементів з функції є прийнятним методом, але chainробить це швидше і краще (у нього є шлях коду до C, тому він швидкий).

  • operator.add(a, b)є прийнятним функціональним еквівалентом a + b. Це випадки використання в основному для динамічного відправлення методу. В іншому випадку, віддайте перевагу, a + bякий коротший і легший для читання, на мій погляд . YMMV.


відповіді на stackoverflow.com/q/36863404/125507 могли б використовувати perfplot ділянку ( в тому числі рішення Numba)
ендоліти

@endolith трохи завалився роботою, але я погляну і побачу, чи зможу я скотитися.
cs95

який найкращий метод, тоді ефективніший, швидший? будь ласка, скажи.
ганешдешмух

@ganeshdeshmukh TL; DR - це все добре, і те, що ви обираєте, - це здебільшого питання стилю. "There's not much difference between these methods but that makes sense given they all have the same order of complexity (linear). There's no particular reason to prefer one over the other except as a matter of style."Рішення, не вказані у моїй відповіді, або закинуті в" Коментарі ", я рекомендую не використовувати.
cs95


51

Це питання безпосередньо задає питання про об'єднання двох списків. Однак це досить високий пошук, навіть коли ви шукаєте спосіб приєднання до багатьох списків (у тому числі, коли ви приєднуєтесь до нульових списків).

Я думаю, що найкращим варіантом є використання розуміння списку:

>>> 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().

Оновлення

Альтернатива, запропонована Патріком Коллінзом у коментарях, також може підійти вам:

sum(a, [])

3
Примітка Python 3: reduceзараз увімкнено, functoolsтому вам потрібно спочатку імпортувати його.
Дімітріс Фасаракіс Хілліард

41

Ви можете просто скористатися оператором +або +=оператором так:

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))

Остання частина може довільно повторно замовляти товари. Якщо ви хочете зберегти порядок, на CPython 3.6+ ви можете зробити цеlist(dict.fromkeys(a + b))
Борис

27

Варто зазначити, що 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може застосовуватися метод класу:

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

22

З Python 3.3+ ви можете використовувати вихід із :

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]

Ви можете використовувати itertools.chain(що еквівалентно) замість визначення власної функції.
Борис

18

Якщо ви хочете об'єднати два списки у відсортованому вигляді, ви можете скористатися mergeфункцією з heapqбібліотеки.

from heapq import merge

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

print list(merge(a, b))

15

Якщо ви не можете використовувати оператор плюс ( +), ви можете скористатися operatorімпортом:

import operator

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

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

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

Крім того, ви також можете використовувати функцію " __add__ Дандер" :

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

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

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

3
Захоплення даундерів, як правило, не найкращий підхід. Якщо +немає за столом, використовуйте operator.add.
Димитріс Фасаракіс Хілліард

2
Чому оператор плюс не буде доступний?
cs01

2
Зазвичай це не буде :), але якщо ви робите зв'язок списку з функцією map або хочете зберегти функцію add у змінній, ви не можете використовувати +.
jpihl

13

Як більш загальний спосіб для більшої кількості списків, ви можете помістити їх у список та використовувати функцію 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).


10

Якщо вам потрібно об'єднати два упорядковані списки зі складними правилами сортування, можливо, вам доведеться прокрутити його самостійно, як у наведеному нижче коді (використовуючи просте правило сортування для читабельності :-)).

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])

Або просто використовувати heapq.merge.
cs95

7

Ви можете використовувати append()метод, визначений на listоб'єктах:

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

9
просто ви знаєте, якщо це ви робите на практиці, це набагато, набагато повільніше, ніж інші запропоновані методи. дивіться stackoverflow.com/questions/17479361/…
Ryan Haining

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

Вищевказаний код, не зберігає порядок, видаляє дублікат із кожного списку (але не з об'єднаного списку)


6

Як вже вказували багато людей, 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
        [...]

Основні моменти, які слід зрозуміти тут, полягають у тому, що списки - це лише окремий випадок ітерабельності, який є об'єктами, як і будь-який інший; і ці for ... inпетлі в python можуть працювати з змінними кортежу, тому просто циклічно працювати на декількох змінних одночасно.


5

Використовуйте просте розуміння списку:

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

Він має всі переваги найновішого підходу використання додаткових розпаковуючих узагальнень - тобто ви можете об'єднати довільну кількість різних ітерабелів (наприклад, списки, кортежі, діапазони та генератори) таким чином - і це не обмежується Python 3.5 або пізнішої версії .


4

Справді стислий спосіб об’єднати список списків

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]

Будь ласка, не використовуйте list.__add__, operator.addа використовуйте натомість. Це більш багатослівний еквівалент, sum(list_of_lists, [])який так само поганий. НЕ ВИКОРИСТОВУВАТИ!
cs95

@ cs95 Ви можете пояснити, у чому проблема, скориставшись списком .__ add__
Акаш Сінгх

Методи "Дандер" є "приватними методами" і зазвичай не повинні використовуватися безпосередньо (їх називають іншими функціями). Винятки становлять obj.__class__і obj.__dict__.
cs95

3

У Python ви можете об'єднати два масиви сумісних розмірів за допомогою цієї команди

numpy.concatenate([a,b])

4
Питання не задає нумету.
cs95

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

Таким чином, ми бачимо, що з двох найпопулярніших методів extendце ефективно.


2
Що робити, якщо мені потрібно додати декілька списків, як-от + b + c + d + e?
Tweakimp

2
@Tweakimp Дивіться цю відповідь, у якій є кілька варіантів (рекомендую chain.from_iterable).
cs95

2

Існує кілька способів об'єднати списки в 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]

1
Чи можете ви поясніть, яку нову інформацію надає ця відповідь стосовно інших?
cs95

Існує декілька способів об'єднати списки в python - про всі вони широко висвітлені в інших набагато старих відповідях. Яку нову інформацію надає ??
Tomerikoo

-1
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]

-1

Якщо ви хотіли нового списку, зберігаючи два старі списки:

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

    sorted(joinedList)

    return joinedList

Чим це відрізняється від відповіді від mingxiao?
Tomerikoo

-2
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]

4
Ну, будь ласка, поясніть
U10-Вперед

У чому сенс аргументів функції, якщо ви використовуєте глобальні імена всередині неї?
Tomerikoo

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.