python字典与集合

字典

  • 字典是一系列由键(key)和值(value)配对组成的元素的集合
  • 在python3.7+字典被确定为有序,其长度大小可变,元素可以任意的增删改。
  • 相比于列表和元组,字典性能更优秀,增删改查操作都可在常数时间复杂度内完成。
'''字典的常用写法'''
# 创建一个保护有数据的字典
# 语法:
#   {key:value,key:value,key:value}
#   字典的值可以是任意对象
#   字典的键可以是任意的不可变对象(int、str、bool、tuple ...),但是一般我们都会使用str
d1 = {'name':'magic', 'age': 20}
d2 = dict({'name':'magic', 'age': 20})
d3 = dict([('name','magic'), ('age', 20)])
d4 = dict(name='magic', age=20)
print(d2)
print(d1 == d2 == d3 ==d4) #True
print(d1['name']) #magic
#print(d1['name2']) 键不存在会抛出异常
#d1.get('name2',None) 不存在时返回一个给定的默认值,解决键不存在抛出异常问题
'''遍历字典'''
for k in d1:  #遍历字典的键
	print(k)
for v in d1.values():  #遍历字典的值
	print(v)
for k, v in d1.items(): #遍历字典的键与值
	print(f"key:{k},value:{v}")
'''字典排序'''
sorted(d1.items(),key=lambda x: str(x[0])) #根据字典键进行升序排序 排序的元素值需要同一类型
sorted(d1.items(),key=lambda x: str(x[1])) #根据字典值进行升序排序  排序的元素值需要同一类型
'''
lambda匿名函数
lambda x: x[0] 
相当于
def f(x):
    return x[0]
'''
#使用zip函数创建字典
index = ['name', 'age', 'sex']
data = [['小明', 22, '男'],['小丽', 18, 'nv']]
d5 = dict(zip(index, data))
print(d5)

集合

  • 集合和字典基本相同,区别是没有键和值的配对,是一系列无序的、唯一的元素组合。
  • 集合不支持索引进行访问、操作,其本质上是一个哈希表,和列表不一样。
'''集合的常用写法'''
s1 = {1, 2, 3, 4, 'magic', 'two'}
s2 = set([1, 2, 3, 4, 'magic', 'two'])
print(s1 == s2) #True
#s1[0] 通过索引下标访问,会抛出异常,集合不支持索引
'''遍历集合'''
for i in s1:  #遍历集合的值
	print(i)
for index,item in enumerate(s1):  #用python内置函数enumerate(),可以返回每个元素与其对应的索引
    print(f"key:{index},value:{item}")
s5 = {1, 2, 3, 4, 5, 6} #排序的元素值需要同一类型
sorted(s5) #对集合的元素进行升序排序

'''通过value in dict/set来判断一个元素在不在字典或集合内'''
print(1 in s1) #True
print('name' in s1) #True
print('magic' in s1) #False 字典这里是通过键key判断的

字典和集合的工作原理

字典和集合的内部结构都是一张哈希表
字典表存储了哈希值(hash)、键和值这三个元素,集合没有键和值的配对,只有单一的元素

老版本的python哈希表结构如下:

哈希值(hash)键(key)值(value)
hash0key0value0
hash1key1value1
hash2key2value2

随着数据存储,它会原来越稀疏,它的存储会类似下面形式:

data = [
['--']['--']['--']
['hash0']['key0']['value0']
['--']['--']['--']
['--']['--']['--']
['hash1']['key1']['value1']
['--']['--']['--']
['hash2']['key2']['value2']
]

这样的设计结构会浪费存储空间,为了提高存储空间利用率
现在的哈希表会把索引和哈希值、键、值分开,形成下面的新结构:
indices索引表

NoneindexNoneindexNoneindexNoneindexNoneindex

data数据表

哈希值(hash)键(key)值(value)
hash0key0value0
hash1key1value1
hash2key2value2

在新的结构存储数据,就会形成下面的形式:

indices = [None, 1 ,None , None , 0 ,None , 2]
data = [
123123213, 'name', 'magic'
'hash--11', 'name', 'long'
12312323, 'age' , 20
]

1. 插入操作

每次想字典或集合插入一个元素时,会首先计算键的哈希值hash(key),
再和mask = PyDicMinSize - 1 做与操作,计算这个元素应该插入哈希表的位置 index = hash(key) & mask
如果位置是空的,那么这个元素就会被插入其中
如果位置被占用,会比较两个元素的哈希值和键是否相等:

  1. 若两者相等,则表明元素已存在,若值不同,则更新值
  2. 若两者不相等,这种情况即是哈希冲突(hash collision)了,在这种情况下,python会继续寻找表中空余位置插入

解决哈希冲突的方法主要有两种,一种是开放寻址法,一种是链表法
哈希冲突的发生,往往会减低操作的速度,因此随着元素不断插入,当剩余空间小于1/3时
python会重新获取更大的内存空间,扩充哈希表,表内所有的元素位置都会被重新排放
哈希冲突和调整大小都会降低效率,但这种情况发生次数极小,平均情况下,保证插入、查找和删除的时间复杂度为O(1)

2. 查找操作
和插入操作类似,计算键的哈希值hash(key),找到其位置,比较哈希表这个位置中元素的哈希值和键,
与需要查找的元素是否相等,如果相等返回,如果不相等继续查找,直到找到空位或者抛出异常为止。

2. 删除操作
对于删除操作,python会暂时对这个位置的元素赋予一个特殊的值,等到重新调整哈希表的大小时,再将其删除。
采用懒惰的处理方式,减少每次删除时间的复杂度,让其均摊。

总结

字典在python3.7+是有序的数据结构,集合是无序的,其内部的哈希表存储结构,保证了其查找、插入、删除操作的高效性。
所以字典和集合通常运用在对元素的高效查找、去重等场景。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值