python基础——数据类型(六)集合

本文最后更新于:1 年前

(一)概述:

集合set是一个无序的唯一确定元素序列。

无序代表着其每次输出时元素的排列顺序可能都不相同。

唯一确定意味着元素是不可重复的,且每个元素互不相同。

元素的个数无限制。

set是可变数据类型,其内容是可以改变的,因此set没有哈希值,不能被用作字典的键或是其他集合的元素。

同一集合中,只能存储不可变的数据类型,不能再存储列表、set集合、字典等可变数据类型元素,因此set集合没有多维形式。(代码见(二)内代码)

(二)创建与形式:

python用{}大括号表示set集合,并用逗号分隔元素。

形式为: setname = { element1 , element2 , ... , elementn }

注意:set没有直接的空集合创建形式。因为直接用{}创建表示的是空字典,而不是空列表,此时应使用***set()***表示空集合。

set创建时若有重复元素,只保留其中一个。(备注:列表去除重复元素最迅速的方法就是转为集合,其运行时间远小于其他去重方法)

set集合内的bool值True不会被创建,只有False才会被创建(不知道为什么)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
a = {1 , "a" , 3.14 , True }
b = {}
bb = set()
c = {1 , 1 , "a" , "a" , 3.14 , 3.14 , False , True}
# d = {[1,2,3],1,2,3} 此句会运行失败,因为不允许在set集合内创建列表。
print(a)
print(type(a))
print(type(b))
print(type(bb))
print(c)
# 运行结果:
# {'a', 1, 3.14}
# <class 'set'>
# <class 'dict'>
# <class 'set'>
# {'a', 1, 3.14, False}

(三)集合的特性:

1. 访问元素:

set集合因其无序,没有索引和下标,一般情况下访问元素只能通过遍历和枚举逐一读取(枚举中会有索引值,但不意味着set有索引)。

遍历一般会使用in关键字。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
a = {1,2,3,4,True,"a","b","c","d"}
for i,v in enumerate(a):
print(i," ",v,end="\n")
for i in a:
print(i,end=" ")
# 运行结果:
# 0 1
# 1 2
# 2 3
# 3 4
# 4 d
# 5 a
# 6 b
# 7 c
# 1 2 3 4 d a b c

2. 删除集合

python自带垃圾回收机制,已创建的集合如不再使用,将会被编译器自动回收,不会产生内存垃圾。

如果需要可以手动删除,使用del 关键字手动删除集合。

形式为: del setname

1
2
3
a={1,2,3,4,5}
del a
print(a) #此句无法输出,因为a已经被删除了,a变量处于未定义状态

3. 集合的关系:

  • 判断子集关系:

    • 使用关系运算符< 、<=、>、>=(用rop指代):

      形式:setname1 rop setname2

      返回True或者False

      当rop为<=,表示子集判断,即当setname1中元素均在setname2中出现时,表示集合1为集合2子集,返回True;否则返回False。

      当rop为<,表示真子集判断,即当setname1中元素均在setname2中出现且setname2有setname1中没有的元素时,表示集合1为集合2真子集,返回True,否则均返回False。

      >=和>的逻辑和前两者相同,但是setname1和setname2的地位互换,表示setname1对setname2的包含和真包含关系。

    • 使用方法:

      1. issubset方法:

        形式:setname1.issubset(setname2)

        setname1<=setname2等价。

      2. issuperset方法:

        形式:setname1.issuperset(setname2)

        setname>=setname2等价。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    a = {1,2,3,4,5,6}
    b = {1,2,3,4}
    c = {1,2,3,4,5,6}
    print(b<a,b>a,b<=a,b>=a,sep="\t")
    print(c<a,c>a,c<=a,c>=a,sep="\t")
    print(b.issubset(a),c.issubset(a),sep="\t")
    print(b.issuperset(a),c.issuperset(a),sep="\t")
    # True False True False
    # False False True True
    # True True
    # False True
  • 集合运算方法:

    • 交集运算:

      形式:setname1&setname2 / setname1.intersection(setname2)

      两个集合可以交换位置,生成结果相同。

      生成一个新集合获得两个集合的所有公共元素。

      可以进行多个集合的连续交运算。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      a={1,2,3,4,5}
      b={3,4,5,6,7}
      c={1,2,3,5,6,7}
      print(a&b)
      print(a.intersection(b))
      print(b.intersection(a))
      print(a&b&c)
      print(c.intersection(a,b))
      # 运行结果:
      # {3, 4, 5}
      # {3, 4, 5}
      # {3, 4, 5}
      # {3, 5}
      # {3, 5}
    • 并集运算:

      形式:setname1 | setname2 / setname1.union(setname2)

      两个集合可以交换位置,生成结果相同。

      生成一个新集合获得两个集合的所有元素,且不重复。

      可以进行多个集合的连续并运算。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      a={1,2,3,4,5}
      b={3,4,5,6,7}
      c={1,2,3,5,6,7,8,9}
      print(a|b)
      print(a.union(b))
      print(b.union(a))
      print(a|b|c)
      print(c.union(a,b))
      # 运行结果:
      # {1, 2, 3, 4, 5, 6, 7}
      # {1, 2, 3, 4, 5, 6, 7}
      # {1, 2, 3, 4, 5, 6, 7}
      # {1, 2, 3, 4, 5, 6, 7, 8, 9}
      # {1, 2, 3, 4, 5, 6, 7, 8, 9}
    • 差集运算:

      形式:setname1 - setname2 / setname1.difference(setname2)

      两个集合可以交换位置,但是生成结果会不同。

      生成一个集合获得setname1中所有不在setname2中出现的元素,即新集合和setname2的交集一定为空集。

      可以进行多个集合的差集运算,得到的是该集合去除其他所有集合含有元素之后的剩余元素。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      a={1,2,3,4,5}
      b={3,4,5,6,7}
      c={1,2,3,5,6,7,8,9}
      print(a-b)
      print(b-a)
      print(a.difference(b))
      print(b.difference(a))
      print(c-a-b)
      print(c.difference(a,b))
      # 运行结果:
      # {1, 2}
      # {6, 7}
      # {1, 2}
      # {6, 7}
      # {8, 9}
      # {8, 9}
    • 对称差集运算:

      形式:setname1 ^ setname2 / setname1.symmetric_difference(setname2)

      两个集合可以交换位置,生成结果相同。

      生成一个集合获得setname1和setname2中不同时出现的元素,即新集合和两个集合的交集的交集一定为空集。

      只能进行多个集合的连续对称差集运算,不能做同时的对称差集运算(也就是每次的运算对象只能有两个)。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      a={1,2,3,4,5}
      b={3,4,5,6,7}
      c={1,2,3,5,6,7,8,9}
      print(a^b)
      print(a.symmetric_difference(b))
      print(a^b^c)
      print(c.symmetric_difference(a.symmetric_difference(b))) #不允许在symmetric_difference方法中加入多个参数。
      # 运行结果:
      # {1, 2, 6, 7}
      # {1, 2, 6, 7}
      # {3, 5, 8, 9}
      # {3, 5, 8, 9}
  • 判断相交方法:

    形式: setname1.isdisjoint(setname2)

    两个集合可以交换位置,生成结果相同。

    两个集合交集为空时返回False,否则返回True(此时有公共元素)。

    不允许连续集合相交判断或者多个集合同时相交判断。

    1
    2
    3
    4
    5
    6
    7
    8
    a={1,2,3,4,5}
    b={3,4,5,6,7}
    c={6,7,8,9}
    print(a.isdisjoint(b))
    print(a.isdisjoint(c)) #isdisjoint方法只接受一个参数
    # 运算结果:
    # False
    # True

4. 集合的增删改查:

  • 向set集合添加元素:

    set集合不支持重复和连接操作(也就是"+"和"*"运算符)。

    • add方法:

      形式:setname.add(element)

      只向set集合添加一个元素,只允许添加不可变类型。

      添加已有元素不对集合进行任何操作。

      1
      2
      3
      4
      5
      6
      a={1,2,3,4,5}
      a.add(6)
      a.add(1)
      print(a)
      # 运行结果:
      # {1, 2, 3, 4, 5, 6}
    • update方法:

      形式:setname.update(elements)

      向set集合中添加传入update的一系列元素,只允许添加不可变类型。

      添加已有元素不对集合进行任何操作。

      update一般是传入另一个集合,会将其所有非公共元素分别加入setname中。

      可以传入非集合的一系列字符串。

      1
      2
      3
      4
      5
      6
      7
      8
      a={1,2,3,4,5}
      b={3,4,5,6,7}
      a.update(b)
      a.update("a","b","c")
      a.update()
      print(a)
      # 运行结果:
      # {1, 2, 3, 4, 5, 6, 7, 'a', 'b', 'c'}
    • 交/差/对称差更新:

      在其相关方法后加_update,不会返回新集合,而是直接将原集合替换为运算结果。(详细方法略,有兴趣请了解difference_update、intersection_update等函数)

  • 删除set集合元素:

    • pop方法:

      形式:setname.pop()

      pop方法从集合中移除并返回一个元素,此元素的选择是随机的。

      注意:如果有一系列数字,从0开始删除,不是完全随机的。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      a={"a",3,1,2,5,6,4,0}
      b={"我","你","她"}
      print(a.pop())
      print(a.pop())
      print(a)
      print(b.pop())
      print(b)
      # 运行结果:
      # 0
      # 1
      # {2, 3, 'a', 5, 6, 4}
      # 你
      # {'她', '我'}、
    • remove方法:

      形式:setname.remove(element)

      从集合中移除指定元素,如果该元素不存在会引发KeyError错误。

      1
      2
      3
      4
      5
      6
      7
      a={1,2,3,4,5,6}
      a.remove(1)
      a.remove(2)
      # a.remove(7) 此句会报错
      print(a)
      # 运行结果:
      # {3, 4, 5, 6}
    • discard方法:

      形式:setname.discard(element)

      和remove要求相同,但是在删除不存在元素时不会报错。

      1
      2
      3
      4
      5
      6
      7
      a={1,2,3,4,5,6}
      a.discard(1)
      a.discard(2)
      a.discard(7)
      print(a)
      # 运行结果:
      # {3, 4, 5, 6}
    • clear方法:

      形式:setname.discard()

      清空元素

      1
      2
      3
      4
      5
      a={1,2,3,4,5,6}
      a.clear()
      print(a)
      # 运行结果:
      # set()
  • 查询set集合元素

    not in和in关键字。

    使用形式不在赘述

    注意:集合的查询时间是θ(1),而列表的时间是θ(n)。

5.集合的其他操作:

内置函数:

  1. len()求集合长度(即元素数量)。

  2. max()求集合内元素最大值。

  3. min()求集合内元素最小值。

  4. sum()求集合元素之和(如果可以求出的话)。

集合的复制:

集合的复制一般不考虑深浅拷贝。

  • 直接赋值:

    = 直接赋值是非拷贝方法。

    两个集合是等价的,修改其中任何一个集合都会影响另一个集合。(代码略)

  • 集合推导式:

    形式:setname1 = { i for i in setname2 }

    利用推导式完成复制。

    1
    2
    3
    4
    5
    a={1,2,3,4,5,6}
    b={i for i in a if i!=1}
    print(b)
    # 输出结果:
    # {2, 3, 4, 5, 6}
  • for循环:略

  • copy方法:

    形式:setname1=setname2.copy()

    1
    2
    3
    4
    5
    a={1,2,3,4,5,6}
    b=a.copy()
    print(b)
    # 输出结果:
    # {1, 2, 3, 4, 5, 6}
  • deepcopy方法:

    格式:setname1= copy.deepcopy(setname2)

    需要import copy库:

    1
    2
    3
    4
    5
    6
    import copy
    a={1,2,3,4,5,6}
    b=copy.deepcopy(a)
    print(b)
    # 输出结果:
    # {1, 2, 3, 4, 5, 6}

排序:

sorted函数排序:略(有需要请看前面的内容)。

(四)不可变集合frozenset :

和set相关,是不可变的,且为hashable,其元素一经创建无法更改。

可以用作字典的键或者其他集合的元素。

set中所有改变集合本身的方法都不支持(如add、remove方法等等),其余的方法都支持。

和set进行集合运算时,返回类型为运算左侧对象对应的类型。

如果set需要不可变就用frozenset来代替。

由元素创建时,frozenset必须由强制转化指定类型。

1
2
3
4
5
6
7
8
9
a=frozenset({1,2,3,4,5,6}) #由强制转化创建
b={4,5,6,7,8,9} #可变
print(type(a&b))
print(type(b&a)) #和右边类型相同
a.issubset(b) #支持不改变集合的set的所用方法
# a.remove(1) 此句报错,frozenset没有改变元素的方法
# 输出结果
# <class 'frozenset'>
# <class 'set'>

python基础——数据类型(六)集合
https://github.com/xiaohei07/xiaohei07.github.io/2023/03/23/python基础——数据类型(六)集合/
作者
07xiaohei
发布于
2023年3月23日
许可协议