如何将可迭代的内容添加到集合中?


Answers:


228

您可以像这样list将a的元素添加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])

2
只是回头看了一下我的解释器会话,我实际上尝试了一下,但由于集表示中的方括号,因此认为它已将整个列表添加为集的元素。我从没注意到他们像那样被代表。
伊恩·麦金农

7
该表示形式使您可以将其直接粘贴回交互式会话中,因为set构造函数将iterable作为其参数。
Frank Kusters

3
请注意,表示只是例如{1, 2, 3}在Python 3,而这是set([1, 2, 3])在Python 2
氡Rosborough

40

为了使任何可能相信(例如)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,但循环添加每个单独项目的成本却是原来的一半。


14

您可以使用set()函数将一个可迭代对象转换为一个集合,然后使用标准集合更新运算符(| =)将新集合中的唯一值添加到现有集合中。

>>> a = { 1, 2, 3 }
>>> b = ( 3, 4, 5 )
>>> a |= set(b)
>>> a
set([1, 2, 3, 4, 5])

5
.update|=示例中的运算符的RHS不同,使用具有这样的好处:参数可以是任意迭代的(不一定是集合)。
tzot

1
好点子。这只是一个美学选择,因为set()可以将可迭代对象转换为集合,但是击键次数相同。
gbc

我以前从未见过该运算符,以后会出现时,我会很乐意使用它。谢谢!
eipxen

1
@eipxen:有|用于联合,&用于相交以及^用于获取一个或另一个但不是两个都存在的元素的方法。但是在一种动态类型的语言中,有时很难阅读代码并知道周围飞来飞去的对象的类型,我感到犹豫使用这些运算符。某个不认识它们的人(或什至根本没有意识到Python允许使用此类操作符)可能会感到困惑,并认为正在进行一些奇怪的按位或逻辑操作。如果这些运算符也可以处理其他可迭代对象,
那就

对此进行了一些时间测试,.update()并在循环中添加了各个元素。发现那.update()更快。我将结果添加到此现有答案中:stackoverflow.com/a/4046249/901641
ArtOfWarfare 2015年

4

只是快速更新,使用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

使用列表理解。

使用列表来短路可迭代的创建:)

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

[编辑:错过了问题的设定部分]


1
我没看到任何东西吗?我想念什么吗?
伊恩·麦金农

-2
for item in items:
   extant_set.add(item)

作为记录,我认为这样的主张“应该有一种-最好只有一种-显而易见的方式”。是假的。它假设许多技术娴熟的人都会做出这样的假设,而每个人的想法都是相同的。对一个人显而易见的东西对另一个人不是那么明显。

我认为我提出的解决方案清晰易读,并且可以满足您的要求。我不相信它会带来任何性能上的损失-尽管我承认我可能会遗漏一些东西。但是尽管如此,对于其他开发人员来说,它可能并不明显且更可取。


啊!像这样的for循环在我的答案中格式化-我永远不会那样做。曾经
jaydel

你是绝对正确的。我编辑了帖子以修复我的损坏。谢谢:)
jaydel

9
您缺少aset.update(iterable)以C速度for item in iterable: aset.add(item)循环而以Python速度循环的要点,每个项目都有一个方法查找和方法调用(aarrgghh !!)。
约翰·马钦

1
抱歉,他在问题中没有提及任何表现,所以我对此并不担心。
jaydel 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.