1、先上代码
dictData = {
'zhangsan': [24, 5000, 'shenzhen'],
'lisi': [25, 10000, 'guangzhou'],
'wangwu': [26, 15000, 'beijing']
}
sortedData = dict(sorted(dictData.items(), key=lambda data: data[0]))
print(sortedData)
看到dictData字典已经按前面的名字由小到大排了序
2、分析一下实现的细节
首先,字典本身是无序的,所以无法直接排序,要做一些转换才行。现在咱们来分析一下,具体是如何转换的。
字典想要排序的话肯定要转换成列表或者元组的方式,排好了序再转换回字典。由于元组没法更改里面的元组,这里我使用转换成列表的方式排序。
用列表的话,如何排序呢?
最简单的方法就是使用Python自带的sorted函数
a = [3, 2, 1]
b = sorted(a)
print(b)
但是这样的话,我们没法看到它里面的实现细节,也就无法真正理解上面一开始的那行实现字典排序的代码。我们可以自己写个简单的冒泡排序给列表排一下序。
a = [11, 12, 15, 10, 22, 1, 5, 3, 4]
def bubbleSort(data):
"""
:param data: list
:return: 返回一个按升序状态排好序的列表
"""
for i in range(len(data) -1):
for j in range(len(data)-i-1):
if data[j] > data[j+1]:
tmp = data[j]
data[j] = data[j+1]
data[j+1] = tmp
return data
print(bubbleSort(a))
将a列表换一种格式的看看,换成这样的
a = [(11, 12), (15, 10), (22, 1), (5, 3)]
def bubbleSort(data):
"""
:param data: list
:return: 返回一个按升序状态排好序的列表
"""
for i in range(len(data) -1):
for j in range(len(data)-i-1):
if data[j] > data[j+1]:
tmp = data[j]
data[j] = data[j+1]
data[j+1] = tmp
return data
print(bubbleSort(a))
可以看到列表已经按照里面的元组的第一个元素排了序
但是如果我们想要输入 a = [(11, 12), (15, 10), (22, 1), (5, 3)] 得到按照元组的第二个元素排序的列表,上面的排序函数就不行了,我们改动一下排序函数
def bubbleSort(data, cmp = None, func = None, reverse = False):
"""
:param data: list
:return: 返回一个按升序状态排好序的列表
"""
for i in range(len(data) - 1):
for j in range(len(data)-i-1):
if func(data[j]) > func(data[j+1]):
tmp = data[j]
data[j] = data[j+1]
data[j+1] = tmp
return data
print(bubbleSort(b, func=lambda data: data[1]))
可以看到列表已经按照元组的第二个元素排好序。到这里是不是很眼熟?我们自己写的排序函数的输入格式是不是和Python自带的sorted函数一模一样?
sortedData = dict(sorted(dictData.items(), key=lambda data: data[0]))
这是上面一开始使用Python自带的sorted函数写的
bubbleSort(b, func=lambda data: data[1])
这是用自己写的函数的
3、dict(sorted(dictData.items(), key=lambda data: data[0]))的写法是什么意思
首先,key=lambda data: data[0]是什么意思?为什么写在函数参数?
这是一个匿名函数,所谓匿名函数就是不用声明直接定义好了就可以使用的函数,当然,在Python里函数不需要声明,但在C或C++里,函数或者方法都要声明好了,然后再定义,定义好了才可以使用,匿名函数不用声明的这一特性就挺不错的。Python这里用到了匿名函数的第二个特性,就是定义函数时不用写def关键字,函数名也不用写,好像没啥用,不过在涉及一些很简单的算法的时候,这个匿名函数,感觉也还不错。
key=lambda data: data[0] 等价于
def funcName(data):
return data[0]
key = funcName
然后 sorted(dictData.items(), key=lambda data: data[0])就是把 key这个函数指针传递到函数下面去了,要使用这个匿名函数的话,直接key(data)就可以了
第二,dict(sorted(dictData.items(), key=lambda data: data[0])) 最外面的dict和dictData.items()的作用又是什么呢?
.items()的作用就是将字典类型的数据转换成一个包含元组的列表
c = {
1: 'x',
2: 'y',
3: 'z'
}
print(c.items())
dict函数作用就是将一个包含元组的列表转换成字典,当然,格式要匹配好
c = {
1: 'x',
2: 'y',
3: 'z'
}
print(c.items())
print(dict(c.items()))
4、测试自己写的将字典排序的函数(不改变原数据格式)
dictData = {
'zhangsan': [24, 5000, 'shenzhen'],
'lisi': [25, 10000, 'guangzhou'],
'wangwu': [26, 15000, 'beijing']
}
def bubbleSort(data, cmp = None, func = None, reverse = False):
"""
:param data: list
:return: 返回一个按升序状态排好序的列表
"""
for i in range(len(data) - 1):
for j in range(len(data)-i-1):
if func(data[j]) > func(data[j+1]):
tmp = data[j]
data[j] = data[j+1]
data[j+1] = tmp
return data
print(dict(bubbleSort(dictData.items(), func=lambda data: data[0])))
TypeError: ‘dict_items’ object is not subscriptable,这个的意思是,
dictData.items()是’dict_items’类的东西,并且无法用下标来获取里面的内容,sorte函数内部自己应该再转换了。那我这里就直接在外面将它转换成列表类型再传进排序函数就可以了。直接list(dictData.items())转换
再来一次
dictData = {
'zhangsan': [24, 5000, 'shenzhen'],
'lisi': [25, 10000, 'guangzhou'],
'wangwu': [26, 15000, 'beijing']
}
def bubbleSort(data, cmp = None, func = None, reverse = False):
"""
:param data: list
:return: 返回一个按升序状态排好序的列表
"""
for i in range(len(data) - 1):
for j in range(len(data)-i-1):
if func(data[j]) > func(data[j+1]):
tmp = data[j]
data[j] = data[j+1]
data[j+1] = tmp
return data
print(dict(bubbleSort(list(dictData.items()), func=lambda data: data[0])))
OK,成功了!
那如果想按照字典里的列表里的某一个元素来排序呢。比如,按照字典里的列表的第三个元素排序。直接将
func=lambda data: data[0] 改成 func=lambda data: data[1][2] 即可
大功告成!
5、总结
sorted(iterable, cmp=None, key=None, reverse=False)
iterable – 可迭代对象。(其实就是字典、列表之类的)
cmp – 比较的函数,这个具有两个参数,参数的值都是从可迭代对象中取出,此函数必须遵守的规则为,大于则返回1,小于则返回-1,等于则返回0。(其实就是传一个保存着一个函数的变量)
key – 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的某一个元素进行排序。(其实也是传一个保存着一个函数的变量)
reverse – 排序规则,reverse = True 降序 , reverse = False 升序(默认)
我自己实现的只是带有key函数的那部分的排序函数,大家感兴趣的可以自己试着加一下带有cmp函数和reverse布尔变量的排序函数。