Python3集合set的入門101練習

集合的特性

去重性、無序性(不可索引)、可hash、可遍歷迭代

set初始化

>>> s1 = set()
>>> s1
set()
>>> s2 = set(range(5))
>>> s2
{0, 1, 2, 3, 4}
>>> s3 = set([1,2,3])
>>> s3
{1, 2, 3}
>>> s4 = set("I love Wayne the master")
>>> s4
{' ', 'I', 'W', 'a', 'e', 'h', 'l', 'm', 'n', 'o', 'r', 's', 't', 'v', 'y'}
>>> s5 ={}
>>> type(s5) #注意這個不是空set
dict
>>> s = {"a","b","c",1,2,3}
>>> s
{1, 2, 3, 'a', 'b', 'c'}
>>> s.add("e")
>>> s
{1, 2, 3, 'a', 'b', 'c', 'e'}
>>> for x in s:
>>>     print(x,hash(x))
1 1
2 2
3 3
c -8405781908541406157
a 2290596625313359349
b 5161925341757322391
e 3106745482966835704

集合的修改:add和update

>>> s.add((3,4))
>>> s
{(3, 4), 1, 2, 3, 'a', 'b', 'c', 'e'}
>>> s.update(range(5))  # update是聯合在一起
>>> s
{(3, 4), 0, 1, 2, 3, 4, 'a', 'b', 'c', 'e'}
>>> s.add((3,4)) #如果已經有,不做改變
>>> s
{(3, 4), 0, 1, 2, 3, 4, 'a', 'b', 'c', 'e'}
>>> s.update(range(5),range(10,15),{1,"a","y"},["a","i"])
>>> s
#把元素拆開放進來
{(3, 4), 0, 1, 10, 11, 12, 13, 14, 2, 3, 4, 'a', 'b', 'c', 'e', 'i', 'y'}

Python集合的刪除

>>> s.remove(10) #如果沒有,則keyerror
>>> s  #使用元素值移除好嗎? #非常好,set是非線性,效率O(1)
{(3, 4), 0, 1, 11, 12, 13, 14, 2, 3, 4, 'a', 'b', 'c', 'e', 'i', 'y'}
>>> s.discard("rr") # 與remove不同在於,不報錯
>>> s
{(3, 4), 0, 1, 11, 12, 13, 14, 2, 3, 4, 'a', 'b', 'c', 'e', 'i', 'y'}
# >>> s.clear()
>>> s
{(3, 4), 0, 1, 11, 12, 13, 14, 2, 3, 4, 'a', 'b', 'c', 'e', 'i', 'y'}
>>> s.pop() # 無序集合的pop
0

Python set的修改

set是非線性結構,沒有修改方法

>>> s = {(3,4),9,8,5,4,2,"d"}

Python集合set的查詢

>>> for x in s:
>>>     print(type(x),x)
<class 'int'> 2
<class 'int'> 4
<class 'int'> 5
<class 'int'> 8
<class 'int'> 9
<class 'str'> d
<class 'tuple'> (3, 4)
>>> 9 in s # in在set中效率是高的
True
%%timeit
>>> a = list(range(100))
>>> -1 in a
4.8 µs ± 38.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%%timeit
>>> b = set(range(100))
>>> -1 in b

# 如上是一個錯誤的實驗對比,因爲set多次range生成造成時間消耗多
4.8 µs ± 61.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%%timeit a = list(range(10000))
>>> -1 in a
213 µs ± 1.34 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%%timeit b = set(range(10000))
>>> -1 in b 
55.1 ns ± 0.394 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

線性數據結構,搜索元素的時間複雜度是O(n),即隨着數據規模增加耗時增大;
set, dict使用hash表實現,內部使用hash值作爲key,時間複雜度爲O(1),查詢時間和數據規模無關,不會隨着數據規模增大而搜索性能下降。

可哈希

數值型int, float, complex
布爾型True, False
字符串string, bytes
tuple
None
以上都是不可變類型,都是可哈希類型, hashables
set的元素必須是可hash的。

集合的特性

去重性、無序性(不可索引)、可hash、可遍歷迭代

set初始化

>>> s1 = set()
>>> s1
set()
>>> s2 = set(range(5))
>>> s2
{0, 1, 2, 3, 4}
>>> s3 = set([1,2,3])
>>> s3
{1, 2, 3}
>>> s4 = set("I love Wayne the master")
>>> s4
{' ', 'I', 'W', 'a', 'e', 'h', 'l', 'm', 'n', 'o', 'r', 's', 't', 'v', 'y'}
>>> s5 ={}
>>> type(s5) #注意這個不是空set
dict
>>> s = {"a","b","c",1,2,3}
>>> s
{1, 2, 3, 'a', 'b', 'c'}
>>> s.add("e")
>>> s
{1, 2, 3, 'a', 'b', 'c', 'e'}
>>> for x in s:
>>>     print(x,hash(x))
1 1
2 2
3 3
c -8405781908541406157
a 2290596625313359349
b 5161925341757322391
e 3106745482966835704

集合的修改:add和update

>>> s.add((3,4))
>>> s
{(3, 4), 1, 2, 3, 'a', 'b', 'c', 'e'}
>>> s.update(range(5))  # update是聯合在一起
>>> s
{(3, 4), 0, 1, 2, 3, 4, 'a', 'b', 'c', 'e'}
>>> s.add((3,4)) #如果已經有,不做改變
>>> s
{(3, 4), 0, 1, 2, 3, 4, 'a', 'b', 'c', 'e'}
>>> s.update(range(5),range(10,15),{1,"a","y"},["a","i"])
>>> s
#把元素拆開放進來
{(3, 4), 0, 1, 10, 11, 12, 13, 14, 2, 3, 4, 'a', 'b', 'c', 'e', 'i', 'y'}

Python集合的刪除

>>> s.remove(10) #如果沒有,則keyerror
>>> s  #使用元素值移除好嗎? #非常好,set是非線性,效率O(1)
{(3, 4), 0, 1, 11, 12, 13, 14, 2, 3, 4, 'a', 'b', 'c', 'e', 'i', 'y'}
>>> s.discard("rr") # 與remove不同在於,不報錯
>>> s
{(3, 4), 0, 1, 11, 12, 13, 14, 2, 3, 4, 'a', 'b', 'c', 'e', 'i', 'y'}
# >>> s.clear()
>>> s
{(3, 4), 0, 1, 11, 12, 13, 14, 2, 3, 4, 'a', 'b', 'c', 'e', 'i', 'y'}
>>> s.pop() # 無序集合的pop
0

Python set的修改

set是非線性結構,沒有修改方法

>>> s = {(3,4),9,8,5,4,2,"d"}

Python集合set的查詢

>>> for x in s:
>>>     print(type(x),x)
<class 'int'> 2
<class 'int'> 4
<class 'int'> 5
<class 'int'> 8
<class 'int'> 9
<class 'str'> d
<class 'tuple'> (3, 4)
>>> 9 in s # in在set中效率是高的
True
%%timeit
>>> a = list(range(100))
>>> -1 in a
4.8 µs ± 38.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%%timeit
>>> b = set(range(100))
>>> -1 in b

# 如上是一個錯誤的實驗對比,因爲set多次range生成造成時間消耗多
4.8 µs ± 61.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%%timeit a = list(range(10000))
>>> -1 in a
213 µs ± 1.34 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%%timeit b = set(range(10000))
>>> -1 in b 
55.1 ns ± 0.394 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

線性數據結構,搜索元素的時間複雜度是O(n),即隨着數據規模增加耗時增大;
set, dict使用hash表實現,內部使用hash值作爲key,時間複雜度爲O(1),查詢時間和數據規模無關,不會隨着數據規模增大而搜索性能下降。

可哈希

數值型int, float, complex
布爾型True, False
字符串string, bytes
tuple
None
以上都是不可變類型,都是可哈希類型, hashables
set的元素必須是可hash的。

練習1:1、 共同好友
你的好友A、B、C,他的好友C、B、D,求共同好友
這是一個交集問題,假設你的好友集合爲{A, B, C},他的好友集合爲{B, C, D}
{‘A’, ‘B’, ‘C’} & {‘B’, ‘C’, ‘D’}
{‘A’, ‘B’, ‘C’}.intersection({‘B’, ‘C’, ‘D’})

your_f = {'A', 'B', 'C'}
his_f ={'B', 'C', 'D'}
print(your_f & his_f)
print(your_f.intersection(his_f))
{'B', 'C'}
{'B', 'C'}

練習2:微信羣提醒:XXX與羣裏其他人都不是微信朋友關係
並集處理
x-userid not in (A | B | C |…) == True,x用戶的ID並不在該羣當前所有成員的好友並集,說明它
不是任何人的朋友。這種方式會產生巨大的並集
假設x用戶的好友列表是T,該羣所有用戶的id集合爲IDs,IDs & T == set()

  • 思路1:
your_f = {'A', 'B', 'C'}
his_1_f ={'B', 'C', 'D'}
his_2_f ={'B', 'C', 'D'}
x_f = {"U"}


# inter = your_f & his_1_f & his_2_f
for i in x_f:
    if (i in your_f) or (i in his_1_f) or (i in his_2_f):
        break
    else:
        print("小心")
小心
  • 思路2:
your_f = {'A', 'B', 'C'}
his_1_f ={'B', 'C', 'D'}
his_2_f ={'B', 'C', 'D'}
x_f = {"U"}

fs = set()
fs.update(your_f)
fs.update(his_1_f)
fs.update(his_2_f)
fs

if x_f not in fs:
    print("小心")
小心

練習3.1: 權限判斷
有一個API,要求權限同時具備A、B、C才能訪問,用戶權限是B、C、D,判斷用戶是否能夠訪問
該API
假設API權限爲集合A,用戶權限爲集合P
A & P == A
A <= P 即 A 是 P的子集
A - P == set() 差集爲空說明P完全包含A
有一個API,要求權限具備A、B、C任意一項就可訪問,用戶權限是B、C、D,判斷用戶是否能夠
訪問該API
假設API權限爲集合A,用戶權限爲集合P
A & P != set() 或 A.isdisjoint§ == False
A - P != A 說明有相交
4、任務處理
一個總任務列表,存儲所有任務。一個已完成的任務列表。找出爲未完成的任務
任務ID不重複
所有任務ID集合放到集合ALL中
所有已經完成的任務ID都放到集合COMPLETED中, 它一定是ALL的子集
ALL - COMPLETED => UNCOMPLETED
5、數字統計
隨機產生2組各10個數字的列表,如下要求: htt

  • 思路1
required_authority = {'A', 'B', 'C'}
user_authority ={'B', 'C', 'D',"A"}
if user_authority & required_authority ==required_authority:
    print("your got pass")
else:
    print("you have no authority")
your got pass
  • 思路2
if required_authority <= user_authority:
    print("your got pass")
else:
    print("you have no authority")
your got pass
  • 思路3
if (required_authority - user_authority) == set():
    print("your got pass")
else:
    print("you have no authority")
your got pass

練習3.2: 權限判斷
有一個API,要求權限具備A、B、C任意一項就可訪問,用戶權限是B、C、D,判斷用戶是否能夠
訪問該API

required_authority = {'A', 'B', 'C'}
user_authority ={'B','E'}
if user_authority & required_authority != set():
    print("your pass")
else:
    print("forbidden")
your pass
required_authority = {'A', 'B', 'C'}
user_authority ={'','E'}
if user_authority.isdisjoint(required_authority): #isdisjoint() 方法用於判斷兩個集合是否包含相同的元素,如果沒有返回 True,否則返回 False
    print("forbidden")
else:
    print("you pass")
forbidden
required_authority = {'A', 'B', 'C'}
user_authority ={'','E'}
if required_authority -  user_authority != required_authority:
    print("your pass")
else:
    print("forbidden")
forbidden
  1. 任務處理
    一個總任務列表,存儲所有任務。一個已完成的任務列表。找出爲未完成的任務。
all_list = {"eat","sleep","play"}
done_list = {"sleep"}
uncompleted_list = all_list - done_list
print(uncompleted_list)
{'eat', 'play'}

練習5: 數字統計
隨機產生兩組數字,如下要求:
每個數字取值範圍[10,20]
統計20個數字中,一共有多少個不同的數字?
2組之間進行比較,不重複的數字有幾個?分別是什麼?
2組之間進行比較,重複的數字有幾個?分別是什麼?
例如,兩組數分別是[1, 9, 5, 7, 4]、[1, 5, 6, 8],兩組數一共有7個不同的數字,兩組間不同的數字
有5個,兩組間重複的數字有2個

group1 = []
group2 = []
import random
for i in range(10):
    group1.append(random.randint(10,20))
    group2.append(random.randint(10,20))
setgroup1 = set(group1)
setgroup2 = set(group2)
print(setgroup1|setgroup2) #setgroup1.update(setgroup2) 一共有多少個不同的數字?
print(setgroup1 ^ setgroup2) # 不重複的數字有幾個?分別是什麼?
print(setgroup1&setgroup2) #重複的數字有幾個?分別是什麼?
{11, 12, 13, 14, 15, 16, 18, 19, 20}
{18, 19, 20, 11, 12, 15}
{16, 13, 14}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章