Last Updated: 2024-03-22 14:58:49 Friday
-- TOC --
Python的set容器是无序不重复的元素集合,set对象的基本使用场景是:
快速的membership testing
$ python -m timeit -s 'a=(1,2,3,4,5,6,7,8)' '8 in a'
5000000 loops, best of 5: 54.5 nsec per loop
$ python -m timeit -s 'a=set((1,2,3,4,5,6,7,8))' '8 in a'
20000000 loops, best of 5: 17 nsec per loop
创建set对象,可以使用set([iterable])
,或者大括号{enum},使用大括号时,枚举集合元素
,否则就是在创建dict对象(语法冲突)。
>>> a = set() # empty set
>>> a
set()
>>> b = set('abcde') # iterable
>>> b
{'e', 'd', 'a', 'b', 'c'}
>>> c = {'abcde'} # enum
>>> c
{'abcde'}
>>> d = {1,2,3,4,5,6} # enum
>>> d
{1, 2, 3, 4, 5, 6}
>>> len(a)
0
>>> len(b)
5
>>> len(c)
1
>>> len(d)
6
>>> f = set([1,2,3,4,5]) # iterable
>>> f
{1, 2, 3, 4, 5}
我们可以通过add()
接口向set中添加元素,但是有个细节需要注意,在Python中,1 == 1.0 为True
,因此:
>>> a = set()
>>> a.add(1)
>>> a.add(1.0)
>>> a
{1}
>>> a.add(1.000000)
>>> a
{1}
>>> 1 == 1.0
True
remove
删除元素。membership testing使用经典的in
关键词:
>>> 'a' in b
True
>>> 'gg' in b
False
set对象属于mutable
,我们可以用add成员函数来增加set对象中的元素,不过如果增加重复元素,操作就无效了,因此我们常常使用set的这个特性来做去重。set对象最特别的应用,就是集合计算,下面这段是来自python官方的示例:
>>> a = set('abracadabra')
>>> b = set('alacazam')
>>> a # unique letters in a
{'a', 'r', 'b', 'c', 'd'}
>>> a - b # letters in a but not in b
{'r', 'd', 'b'}
>>> a | b # letters in a or b or both
{'a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'}
>>> a & b # letters in both a and b
{'a', 'c'}
>>> a ^ b # letters in a or b but not both
{'r', 'd', 'b', 'm', 'z', 'l'}
set对象是一个集合体,无序,我们增加一个元素后,并不能确定这个元素在遍历的时候,出现在什么时候。set对象的实现,肯定对内部元素有一种排序方式,不过对于使用set对象而言,这种内部的排序方式不需要知道,也是不可靠的依据,我们只需要知道无序即可。
set对象用来去重(去掉重复元素)是常用的操作,只需一行代码即可搞定:
>>> a = [1,1,2,2,3,3,4,4,5,5]
>>> list(set(a))
[1, 2, 3, 4, 5]
>>> b = (1,1,2,2,3,3,4,4,5,5)
>>> tuple(set(b))
(1, 2, 3, 4, 5)
在使用setcomp时,依然有去重的效果:
>>> {a for a in (1,2,2,3,3,4,4)}
{1, 2, 3, 4}
使用set对象的union
函数,或者 |
操作符,实现并集操作:
>>> a
{1, 2, 3}
>>> b
{3, 4, 5}
>>> a.union(b)
{1, 2, 3, 4, 5}
>>> b.union(a)
{1, 2, 3, 4, 5}
>>> a
{1, 2, 3}
>>> b
{3, 4, 5}
>>> a | b
{1, 2, 3, 4, 5}
用 + 号是不行的。
用union或 | 合并,会生成一个新的set对象,因此需要用一个额外的变量来指向合并后的结果。也可以使用update
,直接原地修改(in-place):
>>> a
{1, 2, 3}
>>> b
{3, 4, 5}
>>> a.update(b)
>>> a
{1, 2, 3, 4, 5}
>>> b
{3, 4, 5}
>>>
>>> b.update(a)
>>> b
{1, 2, 3, 4, 5}
>>> a
{1, 2, 3}
>>> c
{4}
>>> id(a)
41125032
>>> a |= c
>>> id(a)
41125032
update和 |=
操作一样,原地更新!
使用intersection
函数,或者 &
操作符:
>>> a = {1,2,3}
>>> b = {3,4,5}
>>> c = a.intersection(b)
>>> c
{3}
>>> a
{1, 2, 3}
>>> b
{3, 4, 5}
>>> c = a & b
>>> c
{3}
注意intersection_update
函数与update的异同,都是in-place modification,前者是交,后者是并:
>>> a = {1,2,3}
>>> a.intersection({3,4,5})
{3}
>>> a
{1, 2, 3}
>>> a.intersection_update({3,4,5})
>>> a
{3}
>>>
>>> b = {3,4,5}
>>> b.update({1,2,3})
>>> b
{1, 2, 3, 4, 5}
有两个set,a和b,判断元素在a中而不在b中的方法,可以直接用 -
操作符,或者difference
函数:
>>> a
{1, 2, 3}
>>> b
{3, 4, 5}
>>> a-b
{1, 2}
>>> b-a
{4, 5}
>>> a.difference(b)
{1, 2}
>>> b.difference(a)
{4, 5}
还有 difference_update
函数:
>>> a = {1,2,3}
>>> a.difference({3,4,5})
{1, 2}
>>> a.difference_update({3,4,5})
>>> a
{1, 2}
用两个set交际是否为空可以判断:
>>> a
{1, 2}
>>> b
{3, 4, 5}
>>> a & b == set() # set() creates an empty set
True
更优雅的方法,使用isdisjoint
函数:
>>> a
{1, 2, 3}
>>> b
{3, 4, 5}
>>> a.isdisjoint(b)
False
>>> b.isdisjoint(a)
False
>>> a = {1,2}
>>> a.isdisjoint(b)
True
>>> b.isdisjoint(a)
True
用交集是否与子集相同,可以判断是否为某个集合的子集:
>>> b
{3, 4, 5}
>>> c
{3}
>>> c & b == c
True
更优雅的方式,是使用issubset
函数:
>>> b
{3, 4, 5}
>>> c
{3}
>>> c.issubset(b)
True
>>> b.issubset(c)
False
可以用合并后是否与自己相同来判断是否为对方的超集:
>>> c
{3}
>>> b
{3, 4, 5}
>>> b | c == b
True
更优雅的方法,是用issuperset
函数:
>>> b
{3, 4, 5}
>>> c
{3}
>>> b.issuperset(c)
True
>>> b.issuperset(b)
True
有的时候,我们需要判断,哪些个元素只出现在一个集合中。
>>> a
{1, 2, 3}
>>> b
{3, 4, 5}
>>> (a|b) - (a&b)
{1, 2, 4, 5}
>>> a ^ b
{1, 2, 4, 5}
set对象有个成员函数,symmetric_difference
,干同样的事情,我就是觉得这个函数名太长了:
>>> a = {1,2,3}
>>> b = {3,4,5}
>>> a.symmetric_difference(b)
{1, 2, 4, 5}
>>> b.symmetric_difference(a)
{1, 2, 4, 5}
还有个symmetric_difference_update
函数,用对称差原地更新set对象:
>>> a = {1,2,3}
>>> a.symmetric_difference_update({3,4,5})
>>> a
{1, 2, 4, 5}
>>>
>>> a = {1,2,3}
>>> a.update({3,4,5})
>>> a
{1, 2, 3, 4, 5}
in-place methods
:update,difference_update,intersection_update,symmetric_difference_update
Python内置了两种集合对象,set和frozenset,set是mutable,对应的frozenset就是immutable
。有点类似list和tuple的关系。Immutable的frozenset可以作为dict对象的key(must be hashable),有些场景下,这个操作能够极大的简化代码。
本文链接:https://cs.pynote.net/sf/python/202205051/
-- EOF --
-- MORE --