Python: как добавить содержимое итерируемого в набор? - PullRequest
137 голосов
/ 28 октября 2010

Что такое "один [...] очевидный способ" для добавления всех элементов итерируемого к существующему set?

Ответы [ 6 ]

188 голосов
/ 28 октября 2010

по набору, вы имеете в виду set?

>>> foo = set(range(0, 4))
>>> foo
set([0, 1, 2, 3])
>>> foo.update(range(2, 6))
>>> foo
set([0, 1, 2, 3, 4, 5])
34 голосов
/ 28 октября 2010

Для блага любого, кто может поверить, например, что выполнение aset.add() в цикле будет конкурентоспособным по сравнению с aset.update(), вот пример того, как вы можете быстро проверить свои убеждения перед публикацией:

>\python27\python -mtimeit -s"it=xrange(10000);a=set(xrange(100))" "a.update(it)"
1000 loops, best of 3: 294 usec per loop

>\python27\python -mtimeit -s"it=xrange(10000);a=set(xrange(100))" "for i in it:a.add(i)"
1000 loops, best of 3: 950 usec per loop

>\python27\python -mtimeit -s"it=xrange(10000);a=set(xrange(100))" "a |= set(it)"
1000 loops, best of 3: 458 usec per loop

>\python27\python -mtimeit -s"it=xrange(20000);a=set(xrange(100))" "a.update(it)"
1000 loops, best of 3: 598 usec per loop

>\python27\python -mtimeit -s"it=xrange(20000);a=set(xrange(100))" "for i in it:a.add(i)"
1000 loops, best of 3: 1.89 msec per loop

>\python27\python -mtimeit -s"it=xrange(20000);a=set(xrange(100))" "a |= set(it)"
1000 loops, best of 3: 891 usec per loop

Похоже, что цена за элемент в циклическом подходе в три раза выше, чем в update.

Использование |= set() стоит примерно в 1,5 раза больше, чем update, но вдвое меньше, чем при добавлении каждого отдельного элемента в цикл.

11 голосов
/ 28 октября 2010

Вы можете использовать функцию set () для преобразования итерируемого набора, а затем использовать стандартный оператор обновления набора (| =), чтобы добавить уникальные значения из вашего нового набора в существующий.

>>> a = { 1, 2, 3 }
>>> b = ( 3, 4, 5 )
>>> a |= set(b)
>>> a
set([1, 2, 3, 4, 5])
1 голос
/ 04 февраля 2018

Просто быстрое обновление, время использования Python 3:

#!/usr/local/bin python3
from timeit import Timer

a = set(range(1, 100000))
b = list(range(50000, 150000))

def one_by_one(s, l):
    for i in l:
        s.add(i)    

def cast_to_list_and_back(s, l):
    s = set(list(s) + l)

def update_set(s,l):
    s.update(l)

Результаты:

one_by_one 10.184448844986036
cast_to_list_and_back 7.969255169969983
update_set 2.212590195937082
0 голосов
/ 28 октября 2010
for item in items:
   extant_set.add(item)

Для протокола, я думаю, что утверждение "Должен быть один - и предпочтительно только один - очевидный способ сделать это". подделка Это делает предположение, что многие технические люди думают, что все думают одинаково. То, что очевидно для одного человека, не так очевидно для другого.

Я бы сказал, что предложенное мной решение легко читается и выполняет то, что вы просите. Я не верю, что с этим связаны какие-то проблемы с производительностью, хотя я допускаю, что я что-то упустил. Но, несмотря на все это, это может быть неочевидным и предпочтительным для другого разработчика.

0 голосов
/ 28 октября 2010

Используйте понимание списка.

Короткое замыкание создания итерируемого с использованием списка, например:)

>>> x = [1, 2, 3, 4]
>>> 
>>> k = x.__iter__()
>>> k
<listiterator object at 0x100517490>
>>> l = [y for y in k]
>>> l
[1, 2, 3, 4]
>>> 
>>> z = Set([1,2])
>>> z.update(l)
>>> z
set([1, 2, 3, 4])
>>> 

[Редактировать: пропущена заданная часть вопроса]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...