[Python] Python資料型別(三)集合型別之set集合和frozenset集合
1.集合基本概念
集合是0-n個物件引用的無序組合,集合中儲存的元素不可重複,因此這些物件引用的引用的物件必須是可雜湊運算的 。
1.python中提供了兩種內建的集合型別:可變的set
型別和固定的frozenset
型別。
2.只有可雜湊運算的物件可以新增到集合中,因為集合是無序的,不能儲存重複資料項;
3.可雜湊運算的物件包含一個__hash__()
方法,該方法返回值在整個物件的生命週期都是相同的,可以使用__eq__()
方法進行比較。
4.所有內建的固定資料型別都是可雜湊運算的,比如:int,float,str,tuple,所有內建的可變的資料型別都是不可進行雜湊運算的,比如:dict,list,set.
5.集合中不儲存重複元組,每一項都是唯一的。
2.set集合
set型別是可變的無序序列,因此可以進行新增、移除資料,同時由於是無序的組合型別,因此沒有索引位置 ,故不能使用分片操作符進行操作。
2.1.set的建立
1.建立set型別時,使用{}進行建立,如:
>>> s1 = {"java","12",12}
>>> s1
{'12', 12, 'java'}
str、int都是內建不可變的資料型別,因此可以儲存在set集合中,如果儲存list型別的資料項呢?
>>> l1 = [1,2,3]
>>> s1 = {"java",12 ,l1}
Traceback (most recent call last):
File "<pyshell#633>", line 1, in <module>
s1 = {"java",12,l1}
TypeError: unhashable type: 'list'
這裡報TypeError異常,原因是list是可變型別,沒有hash()方法,不能進行雜湊運算,因此 不能儲存在set中。
2.使用set()建立集合,set()將返回一個空集合:
>>> s = set()
>>> s
set()
>>>
set()中傳入一個set引數時,將返回該set的淺拷貝:
>>> s = set(s1)
>>> s
{'12', 12, 'java'}
>>>
set()中如果傳入其他任意物件,則嘗試將給定的物件轉換為集合:
>>> s = set("set list")
>>> s
{' ', 's', 'l', 't', 'e', 'i'}
>>>
注意:建立空集合時,只能必須用set().不能使用s = {“ss”,1}這種形式,原因是這種形式用於建立另一種資料型別dict.
3.使用集合內涵建立(單獨總結)
2.2.常用操作符和方法:
<,>,<=,>=,==,!=
:比較運算子,逐項進行比較,如果有巢狀,則遞迴比較;
如:
>>> s1 = set("1234")
>>> s2 = set("2134")
>>> s1
{'2', '3', '1', '4'}
>>> s2
{'2', '3', '1', '4'}
>>>
>>> s1 == s2
True
>>>
in、not in
:成員關係符:
>>> "2" in s2
True
>>>
內建len()
方法:
>>> len(s1)
4
>>>
集合操作符:|,&,-,^
,
|
:並集
>>> s1 = set("man")
>>> s2 = set("woman")
>>> s1 | s2
{'o', 'n', 'a', 'w', 'm'}
>>>
&
:交集
>>> s1 & s2
{'m', 'n', 'a'}
>>>
-
:如A-B,表示包含A中但不包含B中元素組成的集合,不支援交換性,如
>>> s1 - s2
set()
>>> s2 -s1
{'o', 'w'}
>>>
^
:對稱差集,A&B以外的元素組成的集合
>>> s2 ^ s1
{'o', 'w'}
>>>
常用方法:
s.add(x)
:將資料項x新增到集合s中
s.clear()
:清空s集合
s.copy()
返回s的淺拷貝
s.difference(t)
:返回一個新集合,包含s中資料項但不包含t中的資料項,等同s-t,如:
>>> s1 = set("chinese")
>>> s2 = set("china")
>>> s1.difference(s2)
{'s', 'e'}
>>> s2.difference(s1)
{'a'}
>>>
s.difference-update(t)
:移除s中和t中都存在的資料項,等同於s-=t
>>> s1
{'h', 'n', 's', 'c', 'e', 'i'}
>>> s2
{'h', 'n', 'a', 'c', 'i'}
>>>
>>> s1.difference_update(s2)
>>> s1
{'s', 'e'}
>>>
s.discard(x)
:從集合s中移除資料項x,如果不存在,則不進行操作:
>>> s = set("discard")
>>> s
{'d', 'a', 's', 'r', 'c', 'i'}
>>> s.discard("s")
>>> s
{'d', 'a', 'r', 'c', 'i'}
>>> s.discard("y")
>>> s
{'d', 'a', 'r', 'c', 'i'}
>>>
s.remove(x)
:從集合s中移除資料項x,如果不存在,則報KeyError
異常:
>>> s
{'d', 'a', 'r', 'c', 'i'}
>>> s.remove("s")
Traceback (most recent call last):
File "<pyshell#762>", line 1, in <module>
s.remove("s")
KeyError: 's'
>>>
s.intersection(t)
:返回s和t的交集集合,等同於s&t
:
>>> s = set("basketball")
>>> t = set("football")
>>> s2 = s.intersection(t)
>>> s2
{'b', 'l', 'a', 't'}
>>>
s.intersection_update(t)
:不返回新的集合,使s變為s和t的交集,等同於s&=t
:
>>> s = set("basketball")
>>> t = set("football")
>>> s&=t
>>> s
{'b', 'l', 'a', 't'}
>>>
s.isdisjoint(t)
:如果集合s和t中沒有相同的項,就返回true:
>>> s.isdisjoint(t)
False
>>>
s.issubset(t)
:如果s等於t或者s是t的子集,則返回True,等同於s<=t
:
>>> s = set("number")
>>> t = set("bignumber")
>>>
>>> s.issubset(t)
True
>>>
s.issuperset(t)
:如果s等於t或者s是t的超集,則返回True,等同於s>=t
:
>>> s = set("number")
>>> t = set("bignumber")
>>> s.issuperset(t)
False
>>> t.issuperset(s)
True
>>>
s.pop()
:返回並移除s中的一個隨機項,如果s為空集,則報KeyError
異常:
>>> s
{'n', 'r', 'b', 'u', 'm', 'e'}
>>> s.pop()
'n'
>>>
s.symmetric_difference(t)
:返回一個新集合,包含s和t的對稱差集,即s和t的交集以外的元素,等同於s ^ t
:
>>> s = set("number")
>>> t = set("big number")
>>> s.symmetric_difference(t)
{' ', 'g', 'i'}
>>>
s.symmetric_difference_update(t)
:不返回一個新集合,使集合s包含s和t的對稱差集,即s和t的交集以外的元素,等同於s ^= t
:
>>> s.symmetric_difference_update(t)
>>> s
{' ', 'g', 'i'}
>>>
s.union(t)
:返回一個新集合,為s和t的並集,等同於s | t
:
>>> s.union(t)
{' ', 'n', 'r', 'g', 'b', 'u', 'm', 'e', 'i'}
>>>
s.update(t)
:將s變為s和t的並集,等同於s |= t
:
>>> s.update(t)
>>> s
{' ', 'n', 'r', 'g', 'b', 'u', 'm', 'e', 'i'}
>>>
2.3.set的常用場景
1.可以用來刪除重複的項,如:
>>> l = list("10101001")
>>> l
['1', '0', '1', '0', '1', '0', '0', '1']
>>> l= list(set("10101001"))
>>> l
['1', '0']
>>>
2.通過將資料存放到set中可以確保沒有重複的資料:
>>> s = set()
>>> s.add("basketball")
>>> s.add("football")
>>> s.add("football")
>>> s
{'football', 'basketball'}
>>>
這種形式常用於for迴圈中進行遍歷時:
for item in set(items)
3.用於刪除不需要的資料:
>>> filenames = {"test.txt","001.log","show.bak"}
>>> for fn in filenames:
if fn.endswith(".txt"):
filenames.discard(fn)
# 出現異常
Traceback (most recent call last):
File "<pyshell#885>", line 1, in <module>
for fn in filenames:
RuntimeError: Set changed size during iteration
這裡出現RuntimeError異常,說明不能使用原來的filenames集合,因此通過set(fileenames)得到一個淺拷貝進行操作:
>>> for fn in set(filenames):
if fn.endswith(".txt"):
filenames.discard(fn)
>>> filenames
{'001.log', 'show.bak'}
>>>
也可用通過集合操作符進行操作如:
>>> filenames = {"test.txt","001.log","show.bak"}
>>> filenames = set(filenames)-{"test.txt"}
>>> filenames
{'show.bak', '001.log'}
>>>
2.4.集合內涵
和列表內涵類似,當集合資料項太長時,可以使用集合內涵類建立集合,集合內涵是一個迴圈表示式,格式如下
S = {expression for item in iterable if condition}
比如要建立一個0-100的偶數集合:
>>> s = {num for num in range(0,100) if num%2 == 0}
>>> s
{0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98}
>>>
集合內涵中的iterable也可以是一個集合內涵。
3.固定集合frozenset型別
frozenset型別集合是指建立之後就不能改變的集合。
3.1.frozenset集合的建立
1.使用frozenset()
進行建立,不給定引數時將返回一個空的固定集合:
>>> fs = frozenset()
>>> fs
frozenset()
>>>
2.帶一個frozenset引數時,將返回該引數的淺拷貝:
>>> frozenset(fs)
frozenset()
>>>
3.傳入其他引數時,將規定的物件轉換為frozenset:
>>> fs = frozenset("frozenset")
>>> fs
frozenset({'o', 'n', 's', 'r', 't', 'f', 'z', 'e'})
>>>
3.2.常用操作符和方法:
固定集合是不變的,因此其支援的方法和操作符不能影響固定集合本身,故對於set集合中不改變本身的方法和操作符都是支援的。
fs.copy()
:返回fs的淺拷貝
>>> fs2 = frozenset("frozenset")
>>> fs = fs2.copy()
>>> fs
frozenset({'o', 'n', 's', 'r', 't', 'f', 'z', 'e'})
>>>
fs.difference(t)
:返回一個新的固定集合,包含在fs中且不在t中的資料項,等同於fs - t
:
>>> fs1 = frozenset("frozenset")
>>> fs2 = frozenset("set")
>>> fs1.difference(fs2)
frozenset({'o', 'n', 'r', 'f', 'z'})
>>>
>>> fs - fs2
frozenset({'o', 'n', 'r', 'f', 'z'})
>>>
fs.intersection(t)
:返回一個新集合,fs和t的交集,等同於fs1 & t
:
>>> fs1 = frozenset("frozenset")
>>> fs2 = frozenset("set")
>>> fs1.intersection(fs2)
frozenset({'s', 'e', 't'})
>>>
>>> fs1 & fs2
frozenset({'s', 'e', 't'})
>>>
fs.isdisjoint(t)
:如果fs和t沒有相同資料項,返回True:
>>> fs1.isdisjoint(fs2)
False
>>>
fs.issubset(t)
:如果fs等於t或者fs為t的子集,則返回True,等同於fs <= t
:
>>> fs2.issubset(fs1)
True
>>>
fs.issupperset(t)
:如果fs等於t或者fs為t的超集,則返回True,等同於fs >= t
:
fs.union(t)
:返回一個新集合,為fs和t的並集,等同於fs | t
:
>>> fs3 = frozenset("fs3")
>>> fs4 = frozenset("fs4")
>>> fs3.union(fs4)
frozenset({'3', '4', 'f', 's'})
>>>
fs.symmetric_difference(t)
:返回一個新集合,為fs和t的對稱差集,等同於fs ^ t
:
>>> fs5 = frozenset("apple")
>>> fs6 = frozenset("people")
>>> fs5.symmetric_difference(fs6)
frozenset({'o', 'a'})
>>>