数据容器——集合(set)

什么是集合?

在Python中,集合由一系列不重复的、不可变的值组成,它们之间没有特定的顺序。常见的元素有整数、浮点数、字符串、元组等。

集合与其他数据结构对比

·列表(Lists):有序且允许重复元素,适用于需要保持元素顺序或重复值的情况。
·元组(Tuples):有序且不允许修改,适用于数据的不可变表示。
·字典(Dictionaries):键值对的无序集合,每个键唯一,用于快速查找。
集合与这些数据结构的主要区别在于其无序性和不重复性,这使得它在数据处理和算法优化中有着独特的用途。
集合的特性:
唯一性:集合中的每个元素都是唯一的,重复的元素会被自动忽略。
无序性:集合中的元素没有固定的顺序,因此不能通过索引来访问。

可迭代性:虽然集合是无序的,但可以通过for循环遍历其所有元素。
不可变性:这意味着字符串、数字、元组(只要元组内的元素也是不可变的)可以作为集合元素。尝试将可变对象(如列表)放入集合会导致错误:
mutable_list = [1, 2, 3]
mutable_set = {mutable_list}  # TypeError: unhashable type: 'list'
# 集合可以使用“{ }”或“set()”函数建立集合。
# 创建2个集合
my_set = {1, 2, 3, 4, 'apple'}
my_set2={"上海","北京","西湖","故宫",1997,"山东","杭州","北京","西湖","新疆","上海"}
#这里,my_set就是一个集合,包含了整数1到4以及字符串'apple'。尝试添加重复元素时,Python会自动忽略它们:
my_set.add(3)  # 由于3已经在集合中,所以不会有任何变化
print(my_set)  # 输出: {1, 2, 3, 4, 'apple'}
# 集合有自动去重的功能,而且输出的结果是打乱顺序的。
print(f"集合{my_set2}的类型为{type(my_set2)}")  # 输出:集合{'杭州', 1997, '故宫', '上海', '山东', '西湖', '北京', '新疆'}的类型为<class 'set'>

集合的创建

# 创建集合有两种主要方式:直接初始化和通过转换其他数据结构。
# 直接初始化
fruits = {'apple', 'banana', 'orange'}
print(fruits) # 输出:{'banana', 'apple', 'orange'}
# 通过列表转换
numbers = list(range(1, 6))
number_set = set(numbers)
print(number_set)  # 输出:{1, 2, 3, 4, 5}
注意:不可变集合(frozensets)
## 与普通的集合不同,frozenset是不可变的,一旦创建,就不能添加或删除元素。这在需要创建一个不可变集合,或者作为字典的键时非常有用。
immutable_fruits = frozenset({'apple', 'banana'})
# 尝试向不可变集合添加元素,将会引发错误
immutable_fruits.add('orange')  # TypeError: 'frozenset' object does not support item assignment

补充:range(start, stop, step)函数

在Python编程中,经常需要生成一系列连续的数字,用于循环、迭代和其他各种操作。
为了方便生成这样的数字序列,Python提供了内置函数range()1、使用range()函数生成数字序列
range()函数用于生成一个数字序列,其基本语法如下:
range(stop):只提供一个参数stop,则生成从0到stop-1的数字序列,默认start值为0,步长为1.
range(start, stop):提供两个参数start和stop,生成从start到stop-1的数字序列。
range(start, stop, step):提供三个参数start、stop和step,则生成从start开始,以step为步长递增或递减的数字序列。
需要注意的是,range()函数生成的数字序列不包括stop的值,即生成的范围是半开区间。
# 示例:使用range()生成数字序列,并使用list()函数将序列转换为列表以便查看结果。

# 生成从0到4的数字序列
sequence1 = range(5)
print(list(sequence1))  # [0, 1, 2, 3, 4]

# 生成从2到6的数字序列
sequence2 = range(2, 7) # 从2开始,默认步长为1,省略没写
print(list(sequence2))  # [2, 3, 4, 5, 6]

# 生成从2到6的数字序列,步长为-2
sequence_2 = range(7, 2,-2)
print(list(sequence_2))  # [7, 5, 3]

# 生成从1到10,以2为步长的数字序列
sequence3 = range(1, 11, 2)
print(list(sequence3))  # [1, 3, 5, 7, 9]
2、使用range()函数生成循环计数器
一个常见的用途是在循环中使用range()函数来充当计数器,从而控制循环的次数。这通常与for循环结合使用。
for i in range(5):
    print(i)
'''
输出结果:
0
1
2
3
4
3、将range()与list()结合使用
虽然range()函数生成的是一个数字序列对象,但有时候我们希望将它转换为列表,以便更方便地查看、操作和使用。
# 生成数字序列并将其转换为列表,首先使用range(1, 6)生成了数字序列,然后使用list()函数将其转换为列表。
sequence = range(1, 6)
print(sequence) # range(1, 6),如果结合list()函数,输出的结果就是变量
number_list = list(sequence)
print(number_list)  # [1, 2, 3, 4, 5]

集合的相关操作

1、添加1个元素
语法:集合.add(元素),加一个元素到集合.
my_set = {1, 2, 3}
my_set.add(4)
print(my_set)  # 输出: {1, 2, 3, 4}
2、添加多个元素(接受一个可迭代对象,将其中的所有元素添加到集合中。如果元素已存在,也不会重复添加。)
语法:集合.update(元素),加多个元素到集合.
my_set.update([5, 6, 7])
print(my_set)  # 输出: {1, 2, 3, 4, 5, 6, 7}
迭代,是访问集合元素的一种方式。在Python中,迭代是通过for循环实现的。
比如给定字符串"Python",每次从中取出一个字符,那么就会依次得到 "P"、"y"、"t"、"h"、"o"、"n".
这种通过for循环依次取出集合中的每一个元素,实现遍历每个元素的过程,就被称为迭代。
可迭代对象不是具体的数据类型,而是指存储了元素的容器对象,且对象定义了iter方法或者getitem方法。常见的可迭代对象包括:列表list、元组tuple、字典dict、集合set、字符串str等,另外生成器generator也是可迭代对象。
a=[1,2,3]  #a为列表
for i in a:
    print(i)
b=("你","我","他")  #b为元组
for j in b:
    print(j)

'''
运行结果:
1
2
3
你
我
他
'''
# 整数int不是可迭代对象。
# 为了满足迭代需求,可以使用range()函数,该函数常常与for...in...命令同时出现,其作用是生成一个数字序列,从而运用for循环实现每个数字的遍历。
'''
c=int(5.2)
for i in c:
    print(i)'''
# 报错:TypeError: 'int' object is not iterable
# 通过int()函数生成的整数在进行for循环时出现报错,原因就是整数int不是可迭代对象。下面的例子中使用range()函数,程序就能够成功执行。
for i in range(1,5):
    print(i)
'''
运行结果:
1
2
3
4
'''
3、移除元素
# 语法1:集合.remove(元素),移除集合中的指定元素。如果元素不存在,会引发KeyError。
my_set.remove(5)
print(my_set)  # 输出: {1, 2, 3, 4, 6, 7}
# 语法2:集合.discard(元素):与remove()类似,但若元素不存在,不会抛出异常。
my_set.discard(8)  # 元素8不在集合中,不会报错
# 语法3:集合.pop(元素):随机取出一个元素。集合为空时,会引发KeyError。
random_element = my_set.pop()
my_set_3={2}
random_element_2= my_set_3.pop()
print(random_element)  # 可能是1, 2, 3, 4, 6或7中的任意一个 # 随机输出移除的数字:1
print(my_set)  # 输出: {剩下的元素}: {2, 3, 4, 6, 7}
print(random_element_2)   # 随机输出移除的数字:2
print(my_set_3) # set()
# 语法4:集合.clear(元素):移除集合中的所有元素。
my_set.clear()
print(my_set)  # 输出: set()

集合的方法和属性

集合提供了许多有用的方法和属性,帮助我们检查集合状态和进行集合间的交互。以下是一些重要的方法和属性。
1、集合的成员资格测试,in 和 not in:用于测试元素是否属于集合。
my_set = {1, 2, 3, 4, 5}
print(3 in my_set)  # 输出: True
print(6 not in my_set)  # 输出: True
2、集合的大小,len():返回集合中元素的数量。
my_set = {1, 2, 3, 4, 5}
print(len(my_set))  # 输出: 5
3、集合的复制,copy():创建集合的一个浅拷贝。
'''
    在Python中,拷贝可以创建一个对象的副本,这个副本可以独立于原始对象进行修改。
    拷贝分为深拷贝和浅拷贝,它们的区别在于拷贝过程中对象内部引用的处理方式。
浅拷贝创建一个新对象,它是原始对象的一个副本,但是这个副本中包含的是对原始对象中元素的引用。
换句话说,浅拷贝不会递归复制对象的内部结构。
实现方式:可以通过copy模块中的copy()函数实现。
适用场景:当对象内部没有可变对象或者不需要复制对象内部的可变对象时。

深拷贝会创建一个新对象,并且递归复制所有对象的子对象,为所有对象创建新的实例。
这意味着深拷贝会复制对象及其子对象的整个层次结构。
实现方式:可以通过copy模块中的deepcopy()函数实现。
适用场景:当对象内部包含可变对象,并且需要完全独立于原始对象的副本时。
'''
copy_set = my_set.copy()
print(copy_set is my_set)  # 输出: False
print(copy_set == my_set)  # 输出: True
4、判断两集合是否无交集
.isdisjoint():如果两个集合没有任何共同元素,返回True。
set1 = {1, 2, 3}
set2 = {4, 5, 6}
print(set1.isdisjoint(set2))  # 输出: True

5 、将其他数据结构转换为集合
set():将列表、元组等可迭代对象转换为集合。
my_list = [1, 2, 2, 3, 3, 3]
unique_set = set(my_list)
print(unique_set)  # 输出: {1, 2, 3} # 自动去除重复的数字

集合的运算

集合中最常见的运算就是并集、交集和差集.
并集:取两集合全部的元素。
交集:取两集合公共的元素。
差集:取一个集合中另一集合没有的元素。
对称差集:取集合 A 和 B 中不属于 A和B 公共的元素,即全集中去掉A和B公共元素的集合。
集合交集--intersection和&
交集运算返回一个新的集合,新集合里的元素存在与所有参与计算的集合中。
#——intersection方法:
语法:s.intersection(set1,...,setN),其中intersection方法可以传入多个集合,最少传入一个集合,因此set1是必须要传入的,
返回的新集合中的元素既在s中,也在set1,set2 ... 中。
set1={"java","c","python","Linux"}
set2={"java"}
intersection_set=set1.intersection(set2)
print(intersection_set)  # 输出:{'java'}

#——&是简单和方便的实现交集的方法,具体如下:
set1={"java","c","python","Linux"}
set2={"java","python"}
print(set1&set2)  # {'java', 'python'}
集合并集:union和|
并集运算:返回一个新的集合,新集合中的元素包含了所有参与运算的集合的元素,你可以理解为将所有集合的元素放在一起组成了一个新的集合。
# union方法
语法定义:s.union(set1,...,setN),union方法允许传入多个集合,set1必传,因为至少需要传入一个集合参与计算,原有的2个集合内容不变'''
set1={"java","c","python"}
set2={"java"}
intersection_set_1=set1.union(set2)
# |方法
intersection_set2=(set1|set2)
print(intersection_set_1)  # 输出:{'c', 'java', 'python'}
print(intersection_set2)  # 输出:{'c', 'java', 'python'}
集合差集:different和“-”
差集运算返回一个新集合,差集运算的结果与运算顺序有关.
比如两个集合s1 和 s2,s1对s2求差集的结果与s2对s1求差集的结果是不相同的,除非s1与s2完全相同,他们的差集是一个空集合。
different方法和“-”方法
##差集语法定义:s1.difference(s2),具体如下:表示s1对s2求差集的结果,得到一个新集合,内含2个集合的差集原有的2个集合内容不变.
set1={"北京","重庆","天津"}
set2={"重庆","广州","苏州","桂林"}
# 集合的差集具有顺序差异
set3=set1.difference(set2)
set4=set2.difference(set1)
set5=set1-set2
print(set3)  # {'北京', '天津'}
print(set4)  # {'桂林', '苏州', '广州'}
print(set5)  # {'天津', '北京'}
# 原有的2个集合内容不变
print(set1) # {'重庆', '北京', '天津'}
print(set2)  # {'重庆', '桂林', '广州', '苏州'}.


# 集合1.difference_update(集合2):在集合1中,删除集合2中存在的元素集合1被修改,集合2不变,并不生成新集合
set1={"哇哈哈","哈根达斯","茶颜悦色","蜜雪冰城","瑞幸"}
set2={"哇哈哈","钟薛高","星巴克","瑞幸"}
set3_1=set1.difference_update(set2)
print(set3_1)  # None
print(set1) # 集合1被修改:{'哈根达斯', '蜜雪冰城', '茶颜悦色'}
print(set2)  # 集合2不变:{'哈根达斯', '蜜雪冰城', '茶颜悦色'}
对称差集:“^”运算符和symmetric_difference()
取集合A和B中不属于A和B的元素
# 使用“^”运算符进行对称差集运算
A = {'语文','数学','英语','政治','历史','地理'}
B = {'语文','数学','英语','物理','化学','生物'}
print(A ^ B)    # 输出集合A和集合B的对称差集:{'政治', '历史', '生物', '地理', '化学', '物理'},没有交集“语文”

# 使用symmetric_difference()方法进行对称差集运算
A1 = {1,2,3,4,5,6,7}
B1 = {2,4,6,8,10}
print(A1.symmetric_difference(B1))  # 输出集合A和集合B的对称差集:{1, 3, 5, 7, 8, 10}
print(A1)  # {1, 2, 3, 4, 5, 6, 7}
print(B1)  # {2, 4, 6, 8, 10}

集合1.symmetric_difference_update(集合2),
#执行结果是集合1.symmetric_difference(集合2)的返回值去更新集合1,而集合2保持不变。集合1.symmetric_difference_update(集合2)的返回值是None。
A1 = {-1,-2,-3,-4,-5,-6,-7}
B1 = {-2,-4,6,-8,10}
print(A1.symmetric_difference_update(B1))  # 输出:None
print(A1)  # {6, 10, -1, -8, -7, -6, -5, -3}
print(B1)  # {6, -8, 10, -4, -2}

集合遍历
集合是一个无序的数据结构,因此它不支持索引、切片或其他类似的序列的操作。不过,可以通过迭代来访问集合中的元素,使用 for 循环遍历集合中的所有元素,因为集合是无序的,所以输出的结果也是无序的。如果你想对集合中的元素进行排序,你可以使用 sorted() 函数
thisset = {4,3,2,1,6,8}
for x in thisset:
  print(x)
'''
1
2
3
4
6
8
'''
# 使用sorted()函数,按升序顺序输出
thisset = {-4,-3,-2,-1,-6,-8}
sorted_set =sorted(thisset)
for x in sorted_set:
  print(x)
'''
-8
-6
-4
-3
-2
-1
'''

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值