python中dict和set的30种操作方法

字典dict

字典(dict),一种映射对象(mapping)类型,键值对的容器

创建字典(五种方法)

手动创建

1
2
dic1 = {} # 创建空字典
dic2 = {'a':1,'c':3,'e':5}

使用 dict() 构造函数

1
2
3
4
dict() #创建空字典
dict(a=1,b=2,c=3) # {'a': 1, 'b': 2, 'c': 3}
dict({'a':1,'b':2},c=3,d=4)
# {'a': 1, 'b': 2, 'c': 3, 'd': 4}

使用可迭代对象

1
2
3
4
dict([('a',1),('b',2)],c=3) #  {'a': 1, 'b': 2, 'c': 3}
dict([('c',3),('d',4),('e',5)]) # {'c': 3, 'd': 4, 'e': 5}
dict([['c',3],['d',4],['e',5]]) # {'c': 3, 'd': 4, 'e': 5}
dict((('c',3),('d',4),('e',5))) # {'c': 3, 'd': 4, 'e': 5}

使用fromkeys() 方法

已知键集合(keys),values 为初始值

1
2
3
4
{}.fromkeys(['k1','k2','k3'],[1,2,3])
# {'k1': [1, 2, 3], 'k2': [1, 2, 3], 'k3': [1, 2, 3]}
{'a':1,'b':2}.fromkeys(['c','d'],[1,2])
# {'c': [1, 2], 'd': [1, 2]}

使用内置函数zip

1
2
3
4
list1 = ['a','b','c','d','e']
list2 = [1,3,2,5,6]
dict(zip(list1,list2))
# {'a': 1, 'b': 3, 'c': 2, 'd': 5, 'e': 6}

遍历字典

  • d.items()将字典转换为可遍历的列表
1
2
3
4
5
6
7
8
9
10
11
d = {'a':1,'b':2,'c':3}
for key, val in d.items():
print(key,val)
"""
输出:
a 1
b 2
c 3
"""
d.items()
# dict_items([('a', 1), ('b', 2), ('c', 3)])

下面的写法会报错

1
2
3
4
5
6
7
In [180]: d = {'a':1,'b':2,'c':3}

In [181]: for key, val in d:
...: print(key,val)
...:
---------------------------------------------------------------------------
ValueError: not enough values to unpack (expected 2, got 1)

可以这样写,直接遍历所有的键

1
2
3
4
5
6
7
In [180]: d = {'a':1,'b':2,'c':3}
In [183]: for key in d:
...: print(key)
...:
a
b
c

获取字典所有键集合

1
2
3
4
5
6
d = {'a':1,'b':2,'c':3,'d':4}
# 方法1
set(d.keys())
# 方法2
set(d)
# {'a', 'b', 'c', 'd'}

获取字典所有值集合

1
2
list(d.values())
# [1, 2, 3, 4]

判断键是否在字典中

1
2
3
4
5
6
7
8
9
In [184]: d = {'a':1,'b':2,'c':3,'d':4}
In [185]: 'c' in d
Out[185]: True

In [186]: 'e' in d
Out[186]: False

In [187]: 'e' not in d
Out[187]: True

获取某键对应的值

1
2
d = {'a':1,'b':2,'c':3,'d':4}
d.get('c') # 3

添加或修改一个键值对

1
2
3
4
5
6
7
8
9
In [189]: d = {'a':1,'b':2,'c':3,'d':4}
# 添加键值对
In [190]: d['e'] = 4
In [191]: d
Out[191]: {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 4}
# 修改键值对
In [192]: d['e'] = 'aa'
In [193]: d
Out[193]: {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 'aa'}

删除一个键值对

1
2
3
d = {'a':1,'b':2,'c':3,'d':4}
del d['d']
d # {'a': 1, 'b': 2, 'c': 3}

获取字典视图

字典自带的三个方法 d.items()、d.keys()、d.values(),分别返回如下对象:

1
2
3
4
5
6
7
8
9
In [194]: d = {'a': 1, 'b': 2, 'c': 3}
In [195]: d.keys()
Out[195]: dict_keys(['a', 'b', 'c'])

In [196]: d.values()
Out[196]: dict_values([1, 2, 3])

In [197]: d.items()
Out[197]: dict_items([('a', 1), ('b', 2), ('c', 3)])

它们都是原字典的视图,修改原字典对象,视图对象的值也会发生改变。

键必须是可哈希的对象

可哈希的对象才能作为字典的键,不可哈希的对象不能作为字典的键,字典的哈希表实现使用从键值计算的哈希值来查找键。

简要的说可哈希的数据类型,即不可变的数据结构(数字类型(int,float,bool)字符串str、元组tuple、自定义类的对象)。如果一个对象是可哈希的,那么在它的生存期内必须不可变(而且该对象需要一个哈希函数)

对于不可变类型而言,不同的值意味着不同的内存,相同的值存储在相同的内存。详情可参考详解Python中的可哈希对象与不可哈希对象

同理,不可哈希的数据类型,即可变的数据结构 (字典dict,列表list,集合set)

dict中键必须是可哈希的对象

  • list是不可哈希对象
1
2
3
4
5
# list是不可哈希对象
In [198]: lst = [1,2]
In [199]: d = {lst:'ok'}
---------------------------------------------------------------------------
TypeError: unhashable type: 'list'
  • 元祖是可哈希对象
1
2
3
4
5
# 元祖是可哈希对象
In [200]: tup = (1,2)
In [201]: d = {tup:'ok'}
In [202]: d[tup]
Out[202]: 'ok'
  • 自定义类的对象也是可哈希的
1
2
3
4
5
6
7
8
9
10
11
12
class Animal:
def __init__(self, name):
self.name=name
def eat(self):
print("i love eat !")

an = Animal('123')
d = {an:'ok'}
d[an]
'''
'ok'
'''

批量插入键值对

  • 使用字典的update方法批量插入键值对
1
2
3
4
In [203]: d = {'a': 1, 'b': 2}
In [204]: d.update({'c':3,'d':4,'e':5})
In [205]: d
Out[205]: {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}

字典键值对存在不插入,不存在则插入

如果仅当字典中不存在某个键值对时,才插入到字典中;如果存在,不必插入(也就不会修改键值对),这种情况下,使用字典自带方法 setdefault

1
2
3
4
5
6
7
8
9
10
11
12
13
In [206]: d = {'a':1,'b':2}
# setdefault返回插入的value值
In [207]: r = d.setdefault('c',3) # r: 3
In [208]: r
Out[208]: 3
In [209]: d
Out[209]: {'a': 1, 'b': 2, 'c': 3}
# 已经存在 'c':3 的键值对,所以 setdefault 时 d 无改变
In [210]: r = d.setdefault('c',33)
In [211]: r
Out[211]: 3
In [212]: d
Out[212]: {'a': 1, 'b': 2, 'c': 3}

将两个字典合并

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
In [213]: d1 = {'a':1,'b':2}

In [214]: {*d1}
Out[214]: {'a', 'b'}

In [215]: {**d1}
Out[215]: {'a': 1, 'b': 2}

In [216]: d2 = {'c':3,'a':2}
# {**d1,**d2} 实现合并 d1 和 d2,返回一个新字典
In [217]: {**d1,**d2} # 后面的key会覆盖前面的
Out[217]: {'a': 2, 'b': 2, 'c': 3}
# {*d1,*d2} 只能合并 d1 和 d2 的键
In [218]: {*d1,*d2}
Out[218]: {'a', 'b', 'c'}

求两个字典的差集

1
2
3
4
5
d1 = {'a':1,'b':2,'c':3}
d2 = {'b':2}
d3 = dict([(k,v) for k,v in d1.items() if k not in d2])
d3
# {'a': 1, 'c': 3}

按字典的key排序

如果直接使用python内置函数sorted,则只是返回key排序后的集合,可以使用lambda按字典的key排序

1
2
3
4
5
6
7
In [220]: d = {'a':5,'d':7,'c':6}

In [221]: sorted(d)
Out[221]: ['a', 'c', 'd']
# 注意是d.items()
In [222]: sorted(d.items(),key = lambda x:x[0])
Out[222]: [('a', 5), ('c', 6), ('d', 7)]

按字典的value排序

1
2
3
In [220]: d = {'a':5,'d':7,'c':6}
In [224]: sorted(d.items(),key = lambda x:x[1])
Out[224]: [('a', 5), ('c', 6), ('d', 7)]

获取字典最大key的value

1
2
3
4
5
6
7
8
9
10
In [225]: d = {'a':3,'c':1,'b':2}
In [226]: max_key = max(d.keys())
In [227]: max_key
Out[227]: 'c'

In [228]: d[max_key]
Out[228]: 1

In [229]: (max_key,d[max_key])
Out[229]: ('c', 1)

获取字典最大value的key

  • 获取字典最大value的key可能有很多
1
2
3
4
5
6
7
# 获取字典最大value的key可能有很多
In [230]: d = {'a':3,'c':3,'b':2}
In [231]: max_val = max(d.values())
In [232]: max_vals = [(key,val) for key,val in d.items() if d[key]==max_val ]

In [233]: max_vals
Out[233]: [('a', 3), ('c', 3)]

集合

集合(set)是一个无序的不重复元素序列,不能用列表直接索引的方式获取集合中的元素

创建集合

可以使用set() 函数创建集合,注意:创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典

1
2
3
4
5
6
7
In [234]: s_1 = set()
In [235]: s_1
Out[235]: set()

In [236]: s_2 = { 'orange', 'pear', 'orange', 'banana'}
In [237]: s_2
Out[237]: {'banana', 'orange', 'pear'}

集合并集

集合并集就是将两个集合中的元素合并

  • 方法1,集合转化为列表,使用列表的特性
1
2
3
4
set1 = {1,3,5,7} 
set2 = {4,5,6}
set(list(set1)+list(set2))
# {1, 3, 4, 5, 6, 7}
  • 方法2,使用集合extend方法
1
2
3
4
5
6
# list添加多个元素的操作是extend
In [279]: s_1.update([1,2,3]) #添加多个元素
In [280]: s_1.update({3,4}) # 添加集合

In [281]: s_1
Out[281]: {1, 2, 3, 4, 'a'}
  • 方法3,使用|运算符
1
2
3
4
5
In [265]: a = {'a','b','c'}
In [266]: b = {'c','d'}

In [268]: a|b
Out[268]: {'a', 'b', 'c', 'd'}

集合交集

1
2
3
4
5
In [265]: a = {'a','b','c'}
In [266]: b = {'c','d'}

In [267]: a & b
Out[267]: {'c'}

集合差集

1
2
3
4
5
6
# 集合a与b的差集:在集合a存在,不在集合b存在的元素
In [265]: a = {'a','b','c'}
In [266]: b = {'c','d'}

In [269]: a-b
Out[269]: {'a', 'b'}

集合异或

1
2
3
4
5
In [265]: a = {'a','b','c'}
In [266]: b = {'c','d'}

In [270]: a^b
Out[270]: {'a', 'b', 'd'}

集合a与b的异或,可以理解为先求出只存在于a的元素集合,在求出只存在于b的元素集合,然后取并集

异或是指相同为1,不同为0

添加元素

集合添加元素的方法是add,list添加元素的方法是append,insert,由于集合中的元素是无序的,因此不支持在指定位置添加元素,故没有insert方法

1
2
3
4
5
6
In [274]: s_1={'banana', 'orange', 'pear'}
In [275]: s_1.add('apple') #添加一个元素


In [277]: s_1
Out[277]: {'apple', 'banana', 'orange', 'pear'}

移除元素

  • 集合的remove和discard方法都可以移除元素
1
2
3
4
5
6
7
8
9
10
In [282]: s_1 = {'apple', 'banana', 'orange', 'pear'}
In [283]: s_1.remove('apple')

InIn [284]:
In [284]: s_1
Out[284]: {'banana', 'orange', 'pear'}

In [285]: s_1.discard('pear')
In [286]: s_1
Out[286]: {'banana', 'orange'}

注意:区别 来了

1
2
3
4
5
6
7
8
9
10
11
In [287]: 'apple' in s_1
Out[287]: False
In [288]: s_1.remove('apple')
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-288-e8c4186ba334> in <module>
----> 1 s_1.remove('apple')

KeyError: 'apple'

In [289]: s_1.discard('apple')

当删除的元素不存在时

  • remove会报错
  • discard不会报错

集合的pop方法也可以移除元素,由于set是无序的,故set.pop()是随机删除元素,也正因此,set没有提供排序函数

所以pop的索引是不能用的,即pop里面不能有参数

1
2
3
4
5
6
7
8
In [290]: print(s_1)
{'orange', 'banana'}

In [291]: s_pop = s_1.pop()
In [292]: s_pop
Out[292]: 'orange'
In [293]: s_1
Out[293]: {'banana'}

set的pop()是随机删除元素

集合元素限制

可哈希的数据类型,即不可变的数据结构(数字类型(int,float,bool)字符串str、元组tuple、自定义类的对象)。如果一个对象是可哈希的,那么在它的生存期内必须不可变(而且该对象需要一个哈希函数)

对于不可变类型而言,不同的值意味着不同的内存,相同的值存储在相同的内存。详情可参考详解Python中的可哈希对象与不可哈希对象

同理,不可哈希的数据类型,即可变的数据结构 (字典dict,列表list,集合set)

集合中的元素必须是可哈希的数据类型

  • 列表是不可哈希的,将不可哈希的列表放入集合中就会报错,如下:
1
2
3
4
5
6
7
In [294]: {[1,2]}
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-294-4a5722e7ef02> in <module>
----> 1 {[1,2]}

TypeError: unhashable type: 'list'
  • 将可哈希的元祖放入列表中,则不会报错:
1
2
In [295]: {(1,2),(1,2,3),(1,2)}
Out[295]: {(1, 2), (1, 2, 3)}
  • bool类型也是可哈希的数据类型
1
2
In [296]: {True,False,True}
Out[296]: {False, True}
  • 字符串也是可哈希的数据类型
1
2
3
In [297]: set1 = {'1','2','1'}
In [298]: set1
Out[298]: {'1', '2'}
  • 自定义类的对象也是可哈希的
1
2
3
4
5
6
7
8
9
10
11
12
13
class Animal:
def __init__(self, name):
self.name=name
def eat(self):
print("i love eat !")

In [306]: an = Animal('狗')
In [307]: set1 = {an}
In [308]: an.name='猫'

In [309]: a = set1.pop()
In [310]: a.name
Out[310]: '猫'

set集合也可以用python内置函数list()将其转化为列表,从而使用list的所有操作方法