Питонический способ создания объединения всех значений, содержащихся в нескольких списках


84

У меня есть список списков:

lists = [[1,4,3,2,4], [4,5]]

Я хочу сгладить этот список и удалить все дубликаты; или, другими словами, применить операцию объединения множества:

desired_result = [1, 2, 3, 4, 5]

Как это сделать проще всего?

Ответы:


152

set.union делает то, что вы хотите:

>>> results_list = [[1,2,3], [1,2,4]]
>>> results_union = set().union(*results_list)
>>> print(results_union)
set([1, 2, 3, 4])

Вы также можете сделать это с более чем двумя списками.


@sth, например, спасибо, но когда я запускаю его, я получаю сообщение об ошибке: Traceback (последний вызов последний): файл "so_example.py", строка 33, в? results_union = set (). union (* result_lists) TypeError: union () принимает ровно один аргумент (3 задано)
AJ.

1
@AJ: согласно документу ( docs.python.org/library/stdtypes.html#set.union ) union()поддерживает только несколько аргументов для Python версии 2.6 или выше. Похоже, вы использовали более раннюю версию, поэтому вам, вероятно, придется использовать явный цикл: total = set(); for x in results_list: total.update(x) (s /; / \ n /)
sth

2
Вы также можете сохранить создание пустого набора, изменив вторую строку наresults_union = set.union(*(set(el) for el in results_list))
Ноэль Эванс

1
@ Jean-FrançoisFabre TypeError: descriptor 'union' requires a 'set' object but received a 'list'в Python 3.6 по крайней мере.
Паритош Сингх

1
Если вы используете, set.union(*results_list)вы привязываете дескриптор метода вручную, то есть отправляете первый элемент results_listкак «self». Это накладывает некоторые странные ограничения: 1. не утиный тип должным образом (теперь первый элемент должен быть набором или экземпляром подкласса набора), и 2. объединение пустого results_listбудет ошибкой (неправильный результат - должен вернуть пустой набор).
wim

12

Поскольку вы, похоже, используете Python 2.5 ( было бы неплохо упомянуть в своем Q, если вам нужен A для версий! = 2.6, кстати, текущий производственный ;-) и вам нужен список, а не набор в качестве Результат, рекомендую:

import itertools

...

return list(set(itertools.chain(*result_list)))

itertools, как правило, является отличным способом работы с итераторами (и, следовательно, со многими видами последовательностей или коллекций), и я настоятельно рекомендую вам ознакомиться с ним. itertools.chain, в частности, документировано здесь .


+1 Прекрасный пример хорошего времени, чтобы окунуться в чудесную itertoolsупаковку.
gotgenes

@Alex спасибо ... отредактировал мой вопрос, чтобы указать версию и снять с себя вину за то, что я так отстал в версиях :) Я сделаю попытку изучить itertools, ценю предложение.
Эй Джей.

@AJ, не вините, мы все можем пострадать от таких ограничений (но, пожалуйста, не забудьте указать в будущих Qs! -); itertools.chainКстати, отлично работает и в Python 2.4.
Alex Martelli

3

Вы также можете следовать этому стилю

In [12]: a = ['Orange and Banana', 'Orange Banana']
In [13]: b = ['Grapes', 'Orange Banana']
In [14]: c = ['Foobanana', 'Orange and Banana']

In [20]: list(set(a) | set(b) | set(c))
Out[20]: ['Orange and Banana', 'Foobanana', 'Orange Banana', 'Grapes']

In [21]: list(set(a) & set(b) | set(c))
Out[21]: ['Orange and Banana', 'Foobanana', 'Orange Banana']    

1

Союзы не поддерживаются списками, которые упорядочены, но поддерживаются наборами. Проверьте set.union .


0

Я использовал следующее, чтобы сделать пересечения, что избавляет от необходимости в наборах.

a, b= [[1,2,3], [1,2]]
s = filter( lambda x: x in b, a)

или же,

s = [ x for x in b if x in a ]

5
Зачем вам вообще хотеть «избегать необходимости в наборах»? Для этого они работают быстрее и четче. И ваш «x в a» выполняет линейный перебор по списку каждый раз, когда вы его выполняете. Фу.
Питер Хансен

наборы требуют приведения типов, и линейная скорость неплохая, если вы не имеете дело с большим N.
Bear

3
"Приведение типов"? В Python? С тех пор как? Наборы в основном представляют собой dicts только с ключами, и они используют сравнения хешей и равенства. Использование «x в a» в списке также выполняет сравнение на равенство. Что все это такое о приведении типов?
Питер Хансен

0

в понимании:

[*{ j for i in lists for j in i }]

или же

[*functools.reduce(lambda x,y: {*x, *y}, lists)]

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.