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}


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