美文网首页
Python内置数据结构之集合set

Python内置数据结构之集合set

作者: 小小小小河 | 来源:发表于2019-01-15 20:33 被阅读0次

    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的元素组成的集合 image
    • 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的元素组成的集合


      image
    • 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)


      image
    • 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
    

    相关文章

      网友评论

          本文标题:Python内置数据结构之集合set

          本文链接:https://www.haomeiwen.com/subject/woludqtx.html