Python入门:Python内置数据结构之集合set

1 集合的基本概念

在计算机科学中,集合(collection)是一组可变数量的数据项(也可能是0个)的组合,这些数据项可能共享某些特征,需要以某种操作方式一起进行操作。一般来讲,这些数据项的类型是相同的,或基类相同(若使用的语言支持继承)。列表(或数组)通常不被认为是集合,因为其大小固定,但事实上它常常在实现中作为某些形式的集合使用。

集合(collection)的种类包括列表,集,多重集,树和图。枚举类型可以是列表或集。

2 集合(集)set

2.1 set的基本概念

与列表不同,在集(set)中,数据项是无序的,也不允许存在相同数据项。集(set)支持添加、删除和查找项目。一些语言内建对集(set)的支持,而在其它语言中,可以利用散列表实现集。Python中内建支持set类型

set是 可变的无序的不重复 的元素的集合

2.2 set的定义、初始化

  • set() -> new empty set object
  • set(iterable) -> new set object
In [1]: s1 = set()

In [2]: s1
Out[2]: set()

In [3]: s2 = set(range(5))

In [4]: s2
Out[4]: {0, 1, 2, 3, 4}

In [5]: s3 = set(list(range(10)))

In [6]: s3
Out[6]: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

In [7]: s4 = {}    #这实际上定义了一个新字典

#In [14]: type(s4)
#Out[14]: dict

In [8]: s4 
Out[8]: {}       #这是一个空字典

In [9]: s5 = {9,10,11}

In [10]: s5
Out[10]: {9, 10, 11}

In [11]: s6 = {(1,2),3,'a'}

In [12]: s6
Out[12]: {(1, 2), 3, 'a'}

In [13]: s7 = {[1],(1,),1}
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-13-aa063e638452> in <module>
----> 1 s7 = {[1],(1,),1}

TypeError: unhashable type: 'list'

由以上可知,在定义、初始化一个set的时候,有几点要注意。

  1. set的元素要求必须可以hash,不可hash的元素加入set会报错TypeError
  2. set是无序的,元素不可以使用索引
  3. set可以迭代
  4. {}代表一个空字典,set不能像元组、列表、字符串一样只需要在符号(如中括号,小括号,引号)中留空来定义一个空容器

2.3 set元素的增加

  • add(element)
  • 增加一个元素到set中
  • 如果元素存在,则什么都不做
In [17]: s1 = {1,2,3,4,5,6,7,8,9}

In [18]: s1.add(9)

In [19]: s1
Out[19]: {1, 2, 3, 4, 5, 6, 7, 8, 9}

In [20]: s1.add(99)

In [21]: s1
Out[21]: {1, 2, 3, 4, 5, 6, 7, 8, 9, 99}  
  • update(*others)
  • 合并其他元素到set中来
  • 参数others必须是可迭代对象
  • 就地修改
In [27]: s1 = {1,2,3,4,5}

In [28]: s1.update(range(8))

In [29]: s1
Out[29]: {0, 1, 2, 3, 4, 5, 6, 7}
#由于set中的元素是不可复制的,这个操作实际上只增加了6,7两个元素
In [30]: s1.update(range(9),range(11,20))

In [31]: s1
Out[31]: {0, 1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 13, 14, 15, 16, 17, 18, 19}
#update方法可以添加多个可迭代对象,一次把元素添加到set中去

2.4 set删除

  • remove(element)
  • 从set中移除一个元素
  • 元素不存在,抛出KeyError异常。
In [1]: s1 = {1,2,3,4,5}

In [2]: s1.remove(5)

In [3]: s1
Out[3]: {1, 2, 3, 4}
#element存在,成功移除

In [4]: s1.remove(100)
#element不存在,报错KeyError
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-4-685aafef4353> in <module>
----> 1 s1.remove(100)

KeyError: 100
  • discard(element)
  • 从set中移除一个元素
  • 元素不存在,什么都不做
In [7]: s1 = {1,2,3,4,5}

In [8]: s1.discard(1)

In [9]: s1
Out[9]: {2, 3, 4, 5}
#元素存在,移除成功
In [10]: s1.discard(100)

In [11]: s1
Out[11]: {2, 3, 4, 5}
#元素不存在,移除失败。无报错或其他任何操作
  • pop() -> item
  • 移除并返回任意元素
  • 空集返回KeyError

因为set是无序的,无法指定索引,只能随机移除

In [12]: s1 = {1,2,3,4,5}

In [13]: s1.pop()
Out[13]: 1
#随机移除,返回移除值1
In [14]: s1 = set()

In [15]: s1.pop()
#s1为空集,无法移除,报错KeyError
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-15-095118de218b> in <module>
----> 1 s1.pop()

KeyError: 'pop from an empty set'
  • clear()
  • 移除所有元素
In [16]: s1 = {1,2,3,4,5}

In [17]: s1.clear()

In [18]: s1
Out[18]: set()

2.5 set的修改、查询

  • 修改
  • 要么删除,要么加入新的元素

set是无序的,无法通过索引指定某一个元素进行修改。所以只有先删除后增加的操作。事实上,修改这个词也只有在有序容器中才有意义,set内部元素本身无序,不存在修改的。

  • 查询
  • 非线性结构,无法查询
  • 遍历
  • 可以迭代所有元素
In [24]: s1 = {1,2,3,4,5}

In [25]: for i in s1:
    ...:     print(i)
    ...:
1
2
3
4
5

虽然set是无序的,但是仍然可以迭代。有序无序和可否迭代无关。

  • 成员运算符
  • in和not in可以判断元素是否在set中
In [26]: s1 = {1,2,3,4,5}

In [27]: 5 in s1
Out[27]: True

In [28]: 55 in s1
Out[28]: False

set中做成员运算符的操作和list相比,不用遍历,效率比较高

2.6 set和线性结构

  • 线性结构的查询时间复杂度是O(n),即随着数据规模的增大而耗时

  • set、dict等结构,内部使用hash值作为key,时间复杂度可以做到O(1),查询时间和数据规模无关

  • 可hash

  • 数值型int,float,complex

  • 布尔型True,False

  • 字符串string,bytes

  • 元组tuple

  • None

  • 以上都是不可变类型,是可哈希类型,hashable

  • set的元素必须是可hash的。(所以set不能成为set的元素)

3 集合运算

3.1 集合运算和集合的一些基本概念

  • 全集
  • 所有元素的集合。例如实数集,所有师叔组成的集合就是全集。
  • 子集subset和超级superset
  • 一个集合A所有元素都在另一个集合B内,A就是B的子集,B是A的超集
  • 真子集和真超集
  • A是B的子集,且A不等于B,则A是B的真子集,B是A的真超集
  • 并集:多个集合合并的结果

  • 交集:多个集合的公共部分

  • 差集:集合中除去和其他集合的公共部分

3.2 集合运算

3.2.1并集

  • 将两个集合A和B的所有的元素合并在一起,组成的集合称为集合A和集合B的并集

如韦恩图所示

  • union(*others)

  • 返回和多个集合合并后的新的集合

In [29]: s1 = {1,2,3}

In [30]: s2 = {6,7,9}

In [31]: s1.union(s2)
Out[31]: {1, 2, 3, 6, 7, 9}

In [32]: s3 = {1,2,3}

In [33]: s1.union(s3)
Out[33]: {1, 2, 3}
  • | 运算符重载
  • 等同于union
In [34]: s1 = {1,2}

In [35]: s2 = {5,6}

In [36]: s1 |s2
Out[36]: {1, 2, 5, 6}
  • update(*others)
  • 和多个集合合并,就地修改
In [38]: s1 = {1,2}

In [39]: s2 = {'a','b'}

In [40]: s3 = {b'332'}

In [41]: s1.update(s2,s3)

In [42]: s1
Out[42]: {1, 2, 'a', 'b', b'332'}
  • |=
  • 等同于update

3.2.2 交集

  • 集合A和B,由所有属于A且属于B的元素组成的集合

  • intersection(*others)

  • 返回和多个集合的交集
In [1]: s1 = set(range(10))

In [2]: s2 = {'a',3,4,7}

In [3]: s3 = {0}

In [4]: s1.intersection(s2,s3)
Out[4]: set()
# s1,s2,s3无共同交集,返回空集
In [1]: s1 = set(range(10))

In [2]: s2 = {'a',0,9,'sss'}

In [3]: s3 = {0,1,2,3,4,5,6,7}

In [4]: s1.intersection(s2,s3)
Out[4]: {0}
# s1,s2,s3有共同元素0,返回由0组成的集合
  • &
  • 等同于intersection
In [7]: s1 = set(range(10))

In [8]: s2 = set(range(5))

In [9]: s1 & s2
Out[9]: {0, 1, 2, 3, 4}
# s2 是s1的子集,返回了由s2中全部元素组成的集合
  • intersection_update(*others)
  • 获取和多个集合的交集,并就地修改
In [10]: s1 = {'a',1,2,3,4,5,6,7}

In [11]: s2 = set(range(1,5))

In [12]: s3 = {4,5,6,7,8,9,0}

In [13]: s1.intersection_update(s2,s3)

In [14]: s1
Out[14]: {4}
# s1已经被修改为之前的s1,s2,s3的交集
  • &=
  • 等同intersection_update

3.2.3 差集

  • 集合A和B,由所有属于A且不属于B的元素组成的集合
  • difference(*others)
  • 返回和多个集合的差集
In [15]: s1 = set(range(15))

In [16]: s2 = set(range(7,10))

In [17]: s3 = {1,4,7,9,5}

In [18]: s1.difference(s2,s3)
Out[18]: {0, 2, 3, 6, 10, 11, 12, 13, 14}
# 返回了s1和s2、s3的差集
  • 等同diffrence
  • difference_update(*others)
  • 获取和多喝集合的差集并就地修改
In [19]: s1 = set(range(15))

In [20]: s2 = set(range(7,10))

In [21]: s3 = {1,4,7,9,5}

In [22]: s1.difference_update(s2,s3)

In [23]: s1
Out[23]: {0, 2, 3, 6, 10, 11, 12, 13, 14}
#s1修改为s1和s2、s3的差集

In [28]: s1 = set(range(15))

In [29]: s2 = set(range(10))

In [30]: s3 = set(range(10,15))

In [31]: s1.difference_update(s2,s3)

In [32]: s1
Out[32]: set()
#当s1和s2、s3差集为空时,s1被修改为空集
  • -=
  • 等同于diffrence_update()

3.2.4 对称差集

  • 集合A和B,由所有不属于A和B的交集元素组成的集合,记作(A - B)∪(B - A)

  • sysmmetric_differece(other)

  • 返回和另一个集合的对称差集
  • ^
  • 等同sysmmetric_differece()
In [33]: s1 = set(range(10))

In [34]: s2 = set(range(7,15))

In [35]: s1 ^ s2
Out[35]: {0, 1, 2, 3, 4, 5, 6, 10, 11, 12, 13, 14}
#返回的是A对B的差集和B对A的差集的并集
#如果A等于B返回空集
  • sysmmetric_differece_update(other)
  • 获取和另一个集合的对称差集并就地修改
  • ^=
  • 等同于sysmmetric_differece_update()
In [33]: s1 = set(range(10))

In [34]: s2 = set(range(7,15))

In [36]: s1 ^= s2

In [37]: s1
Out[37]: {0, 1, 2, 3, 4, 5, 6, 10, 11, 12, 13, 14}
#s1被修改为s1和s2的对称差集

3.3 集合运算的其他操作

  • issubset(other)、 <=
  • 判断当前集合是否是另外一个集合的子集
In [38]: s1 = set(range(7))

In [39]: s2 = {1,3,5}

In [40]: s2 <= s1
Out[40]: True
  • set1 < set2
  • 判断set1是否是set2的真子集

由于这些判断太简单了,就不贴代码了

  • issuperset(other)、 >=

  • 判断当前集合是否是other的超集

  • set1 > set2

  • 判断set1是否是set2的真超集

  • isdisjoint(other)

  • 当前集合和另外一个集合是否由交集,没有交集,返回True

In [41]: s1 = set(range(10))

In [42]: s2 = {1,3,7}

In [43]: s1.isdisjoint(s2)
Out[43]: False

In [44]: s3 = {-1,-3}

In [45]: s1.isdisjoint(s3)
Out[45]: True
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值