1. 程式人生 > >[Python] Python資料型別(三)集合型別之set集合和frozenset集合

[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'})
>>>