集合讲解
1. python集合定义
python的集合也是容器,其内元素都是无序、唯一、不可变的,常用来做成员测试、移除重复数据、数据计算(如交集、并集等)。集合内元素是唯一的,说明集合中的元素必须是可hash对象。集合不记录元素位置和插入顺序,因此,也不支持索引,切片等其他序列类的操作。
python中可哈希的数据类型,即不可变的数据结构,包括数值类型(int,float,bool)字符串str、元组tuple、自定义类的对象。不可哈希的数据类型,即可变的数据结构,包括字典dict,列表list,集合set。
集合的元素都是可哈希,但集合却不可哈希,可哈希的数据结构,一旦建立,是不允许修改的,比如添加、删除等,而集合却允许。
集合Set就像是字典dict的无value版,定义集合可以使用{} 或者 set(),但定义空集合不能使用{} ,因为{ } 是创建空字典的方法,定义空集合可以使用set()。
下面分别用{} 和 set() 演示如何创建集合
language_set = {'java', 'c', 'python'}
type(language_set)
print(language_set)
# {'c', 'python', 'java'}
# <class 'set'>
name_set = set() # 定义空集合
x = set("abcde")
print(x)
#结果是:{'b', 'e', 'c', 'a', 'd'}
fruits_set = set(['apple', 'orange', 'banana', 'apple']) # 定义时可以有重复元素,但是输出时会去重
print(fruits_set)
# {'banana', 'orange', 'apple'}
如无必要,不要写成如下形式
my_set = set('apple') #如果apple不加花括号,而是加引号时,y 的集合里含有'a','p','p','l','e'四个元素。
print(my_set)
#结果是无序去重的 {'l', 'e', 'p', 'a'}
>>> my_set1 = set(('apple'))
>>> my_set1
{'l', 'e', 'p', 'a'}
在定义fruits_set时,字符串apple存在重复的情况,但python集合会自动去重,因此在输出时,apple并没有重复。去除重复元素是集合的一项重要功能,此外还有成员检测,数学上集合类的计算,例如交集,并集,差集等操作。
上面提到集合中的元素必须是不可变数据,但集合自身是可变的,可以修改其中的元素,此外,python提供了另一种不可变的集合类型frozenset:
s=frozenset("abc")
# 结果是 frozenset({'b', 'a', 'c'})
2. python集合常用基础操作
2.1 add,update方法添加新元素
add方法向集合中添加新的元素,语法如下:
s.add(element)
add方法将element添加到集合s中,如果集合s已经包含了element,则不进行任何操作,集合中的元素具有唯一性,绝不会出现重复的情况。加入的元素必须是可hash的,否则引发异常,比如向集合中添加字典就是不可行的。
language_set = {'java', 'c', 'python'} # 定义集合
language_set.add('c++')
print(language_set) # {'python', 'java', 'c++', 'c'}
update方法同样可以向集合中添加新的元素,且可以一次性添加多个,update方法的本质是先计算两个集合的并集,在用并集更新原集合。
update语法如下:
s.update(seq)
seq参数可以是列表,元素,集合
language_set = {'java', 'c', 'python'} # 定义集合
language_set.update(['node.js', 'php']) # 传入列表
print(language_set) # {'python', 'php', 'java', 'c', 'node.js'}
language_set.update(('javascript', 'c#')) # 传入元组
print(language_set) # {'python', 'php', 'javascript', 'java', 'c', 'c#', 'node.js'}
language_set.update({'vb', 'go'})
print(language_set) # {'python', 'java', 'c', 'javascript', 'c#', 'go', 'vb', 'php', 'node.js'}
s.update( "字符串" ) 与 s.update( {"字符串"} ) 含义不同:
- s.update( {"字符串"} ) 将字符串添加到集合中,有重复的会忽略。
- s.update( "字符串" ) 将字符串拆分单个字符后,然后再一个个添加到集合中,有重复的会忽略。
>>> thisset = set(("Google", "Runoob", "Taobao"))
>>> print(thisset)
{'Google', 'Runoob', 'Taobao'}
>>> thisset.update({"Facebook"})
>>> print(thisset)
{'Google', 'Runoob', 'Taobao', 'Facebook'}
>>> thisset.update("Yahoo")
>>> print(thisset)
{'h', 'o', 'Facebook', 'Google', 'Y', 'Runoob', 'Taobao', 'a'}
>>>
2.2 remove,discard, pop方法删除集合元素
python的集合提供了3种删除元素的方法,分别是remove,discard, pop。
remove方法语法是
s.remove(element)
remove方法将element从集合中删除,需要注意的是如果element不在集合中,remove方法将会发生错误
>>> language_set = {'java', 'c', 'python'}
>>> language_set.remove('c')
>>> language_set.remove('c++')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'c++'
remove是一种不安全的删除集合元素的方法(没有该元素时会报错),想要安全的删除集合元素,可以使用discard方法,当被删除的元素不存在时discard不会发生错误,discard语法如下:
s.discard(element)
示例代码
>>> language_set = {'java', 'c', 'python'}
>>> language_set.discard('c')
>>> language_set.discard('c++')
>>> language_set
{'java', 'python'}
remove和discard方法都没有返回值,它们原地修改集合。
pop方法比较特殊,它的语法定义如下
s.pop()
pop方法没有参数,它随机的删除一个元素并返回该元素,当集合为空时,pop方法会引发KeyError异常。
>>> language_set = {'java', 'c', 'python'}
>>> language_set.pop()
'java'
>>> language_set.pop()
'c'
>>> language_set.pop()
'python'
>>> language_set.pop()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'pop from an empty set'
clear方法清空集合
语法定义
s.clear()
clear方法会将集合中所有元素都删除,python集合的clear方法会移除集合中的所有元素,从作用上看,为变量赋值一个空集合与使用clear方法清空集合有这相同的功效,但clear方法没有产生新的集合,而是修改了原有集合;赋值一个新的空集合,原有的集合对象就不存在了。
>>> language_set = {'java', 'c', 'python'}
>>> language_set.clear()
>>> language_set
set()
2.3 获取集合元素个数
获取集合中元素的个数,使用len内置函数
>>> language_set = {'java', 'c', 'python'}
>>> len(language_set)
3
2.4 获取集合中的元素
由于集合不支持索引,因此无法像列表那样通过索引操作来获取元素,只能通过for循环遍历集合
language_set = {'java', 'c', 'python'} # 定义集合
for language in language_set:
print(language)
程序输出结果
java
python
c
2.6 判断元素是否在集合中
判断一个元素是否在集合中需要使用成员运算符 in
>>> language_set = {'java', 'c', 'python'}
>>> 'java' in language_set
True
>>> 'c++' in language_set
False
3. 集合交集,并集,差集运算
python集合最常用的3个运算是求集合的交集,并集,差集,它们在编程中的作用非常重要。
>>> # 下面展示两个集合间的运算.
...
>>> a = set('abracadabra')
>>> b = set('alacazam')
>>> a
{'a', 'r', 'b', 'c', 'd'}
>>> a - b # 集合a中包含而集合b中不包含的元素
{'r', 'd', 'b'}
>>> a | b # 集合a或b中包含的所有元素
{'a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'}
>>> a & b # 集合a和b中都包含了的元素
{'a', 'c'}
>>> a ^ b # 不同时包含于a和b的元素
{'r', 'd', 'b', 'm', 'z', 'l'}
3.1 集合交集
交集运算返回一个新的集合,所谓交集,是指多个集合相同的部分。新集合里的元素存在于所有参与计算的集合中,语法定义如下
s.intersection(set1, set2 ... etc)
intersection方法可以传入多个集合,最少传入一个集合,因此set1是必须要传入的,返回的新集合中的元素既在s中,也在set1,set2 ... 中。
>>> language_set_1 = {'java', 'c', 'python'}
>>> language_set_2 = {'java', 'php'}
>>> intersection_set = language_set_1.intersection(language_set_2)
>>> intersection_set
{'java'}
>>> intersection_set = language_set_2.intersection(language_set_1)
>>> intersection_set
{'java'}
字符串java既在language_set_1中,也在language_set_2中,language_set_1调用intersection 和 language_set_2 调用intersection方法,得到的交集是相同的。
intersection_update功能作用
python集合的intersection_update方法先计算多个集合的交集然后用交集更新替换原集合,intersection方法是返回集合的交集,而intersection_update则是删除交集以外的其他元素。如果交集是空集合,那么原集合最终也被更新为空集合。
intersection_update方法语法
s.intersection_update(s1, s2 ...)
intersection_update的参数是可变参数,可以接收多个参数,至少传入一个参数
参数
- s1 必传的集合
- s2 可以不传,有多个集合需要进行计算时传入,还可以继续传入s3, s4
返回值
intersection_update方法没有返回值,原地修改集合
示例代码
>>> set1 = {'python', 'c', 'java'}
>>> set2 = {'c', 'java'}
>>> set1.intersection_update(set2)
>>> set1
{'c', 'java'}
set1 与 set2 的交集是{'c', 'java'},intersection_update先计算出交集然后用这个交集更新set1,下面看一个没有交集的例子
>>> set1 = {'python', 'c', 'java'}
>>> set2 = {'node'}
>>> set1.intersection_update(set2)
>>> set1
set()
3.2 集合并集
并集运算返回一个新的集合,新集合中的元素包含了所有参与运算的集合的元素,你可以理解为将所有集合的元素放在一起组成了一个新的集合。
语法定义
s.union(set1, set2...)
union方法允许传入多个集合,set1必传,因为至少需要传入一个集合参与计算。
>>> language_set_1 = {'java', 'c', 'python'}
>>> language_set_2 = {'java', 'php'}
>>> union_set = language_set_1.union(language_set_2)
>>> union_set
{'java', 'c', 'php', 'python'}
3.3 集合差集
差集运算返回一个新集合,差集运算的结果与运算顺序有关,比如两个集合s1 和 s2,s1对s2求差集的结果与s2对s1求差集的结果是不相同的,除非s1与s2完全相同,他们的差集是一个空集合,s1.difference(s2)的结果是在s1中去掉s2中的值,s2.difference(s1)的结果是在s2中去掉s1中的值
差集语法定义如下
s1.difference(s2)
实例代码
>>> language_set_1 = {'java', 'c', 'python'}
>>> language_set_2 = {'java', 'php'}
>>> diff_set = language_set_1.difference(language_set_2)
>>> diff_set
{'c', 'python'}
>>> diff_set = language_set_2.difference(language_set_1)
>>> diff_set
{'php'}
difference_update方法功能作用
python字典的difference_update方法从一个集合中删除另一个集合的所有元素,本质上就是删除两个集合的交集部分。与difference方法对比,difference方法返回两个集合的交集,而difference_update则是从原集合里删除两个集合的交集部分。
difference_update语法
s1.difference_update(s2)
参数
- s2 另一个集合
返回值
difference_update 没有返回值,它原地修改集合
实例代码
>>> set1 = {'python', 'c', 'java'}
>>> set2 = {'c', 'java'}
>>> set1.difference_update(set2)
>>> set1
{'python'}
两个集合做difference_update操作,哪个集合调用这个方法,哪个集合被修改
>>> set1 = {'python', 'c', 'java'}
>>> set2 = {'c', 'java'}
>>> set2.difference_update(set1)
>>> set2
set()
从set2中删除所有set1中的元素,最后set2变为空集合。
4.集合推导式
类似列表推导式,同样集合支持集合推导式(Set comprehension):
>>> a = {x **for** x **in** 'abracadabra' **if** x **not** **in** 'abc'}
>>> a
{'r', 'd'}
5. 集合常用方法
方法 | 描述 |
---|---|
add() | 为集合添加新元素 |
clear() | 删除集合中的所有元素 |
copy() | 拷贝一个集合 |
difference() | 返回多个集合的差集 |
difference_update() | 从一个集合中删除另一个集合的所有元素,本质上就是删除两个集合的交集部分 |
discard() | 删除集合中指定的元素,元素不存在时不会引发异常 |
intersection() | 返回集合的交集 |
intersection_update() | 计算多个集合的交集然后用交集更新替换原集合 |
isdisjoint() | 判断交集是否为空 |
issubset() | 判断集合是否是另一集合的子集 |
issuperset() | 判断集合是否包含另外一个集合 |
pop() | 随机删除集合中的元素 |
remove() | 移除集合中指定元素,元素不存在时会引发异常 |
symmetric_difference() | 返回两个集合中不重复的元素集合。 |
symmetric_difference_update() | python集合的symmetric_difference_update方法与symmetric_difference类似,都是计算两个集合不重复的部分,区别是symmetric_difference方法返回不重复元素组成的集合,而symmetric_difference_update用这个新集合更新原集合 |
union() | 返回两个集合的并集 |
update() | 计算原集合与另一个集合的并集,并用计算得出的并集更新原集合 |
集合 (set) 练习题
集合 (set) 是python 的基础数据类型,本练习题主要考察你对集合的交集,并集,差集的理解和运用,这三个操作,是集合最常见也是最为重要的操作
集合基本操作
集合间的运算
lst1 = [1, 2, 3, 5, 6, 3, 2]
lst2 = [2, 5, 7, 9]
- 哪些整数既在lst1中,也在lst2中
- 哪些整数在lst1中,不在lst2中
- 两个列表一共有哪些整数
虽然题目一直在问两个列表,但用列表解答这3个题目效率很低,你应该用集合
lst1 = [1, 2, 3, 5, 6, 3, 2]
lst2 = [2, 5, 7, 9]
set1 = set(lst1)
set2 = set(lst2)
# 哪些整数既在lst1中,也在lst2中
print(set1.intersection(set2))
# 哪些整数在lst1中,不在lst2中
print(set1.difference(set2))
# 两个列表一共有哪些整数
print(set1.union(set2))