python提供内置的排序函数sorted()和列表排序的函数sort(), 灵活使用这两个函数足以完成大多数排序的需求, 当然也可以手写排序函数, 其中, sort函数有三个参数sort(*, key=None, reverse=None), 第一个参数一般不用, 第二个参数指定排序的关键词, 第三个参数表示是否逆序, 默认数字按大小,字符串按字典序升序排序,对于多属性对象,也可以指定关键字排序,后面说到
1. 对列表排序
nums = [10, 3, 4, 1, 2, 9, 6, 5, 8, 7, 0]
对于只有单一属性元素的列表,可以直接使用a.sort()排序, 如果想要降序排序, 则加参数“reverse = True”即可
nums.sort() #升序排序
nums.sort(reverse = True) #降序排序
同样可以使用内置函数sorted实现排序,返回一个有序序列
tnums = sorted(nums) #返回一个升序序列给tnums
tnums = sorted(nums, reverse = True) #返回一个降序序列
对于复合型列表指定关键词排序
nums = [("ten", 10), ("three", 3), ("four", 4), ("one", 1), ("two", 2), ("nine", 9)]
按元组列表中的单词排序
nums.sort(key = lambda x : x[0])
输出排序结果:
[('four', 4), ('nine', 9), ('one', 1), ('ten', 10), ('three', 3), ('two', 2)]
按元组列表中的数字排序
nums.sort(key = lambda x : x[1])
输出排序结果:
[('one', 1), ('two', 2), ('three', 3), ('four', 4), ('nine', 9), ('ten', 10)]
2. 对字典进行排序
不要奢望python能像c++一样企图得到一个有序的dict,因为python使用的hash实现字典, 这是不可能的, 但是能将字典排序后的内容保存到一个列表中.
enum = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"]
nnum = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
sdict = dict(zip(nnum, enum)) #使用上面两个列表生成key为数字, value为字符串的字典
tdict = sorted(sdict.items(), key = lambda x : x[1]) #使用sorted函数对字典按value排序
按value值排序输出
8 eight
5 five
4 four
9 nine
1 one
7 seven
6 six
10 ten
3 three
2 two
0 zero
对dict按key降序排序
tdict = sorted(sdict.items(), key = lambda x: x[0], reverse = True)
输出按key排序后的结果
0 zero
1 one
2 two
3 three
4 four
5 five
6 six
7 seven
8 eight
9 nine
10 ten
3. 按对象的属性排序
定义book类,有书名和价格两个属性, 然后对book对象排序
class book:
def __init__(self, name, price):
self.name = name
self.price = price
def __str__(self):
return "name: " + str(self.name) + ", price: " + str(self.price)
生成对象列表
name = ["ed", "dfw", "zert", "gwert", "rgsd", "hkjhi", "ydfg", "indf", "kjsdf", "kenfs"]
price = [123, 435, 12, 56, 23, 12, 674, 123, 3452, 979]
books = list(book(x, y) for x, y in zip(name, price))
for x in books:
print(x)
输出原始序列
name: ed, price: 123
name: dfw, price: 435
name: zert, price: 12
name: gwert, price: 56
name: rgsd, price: 23
name: hkjhi, price: 12
name: ydfg, price: 674
name: indf, price: 123
name: kjsdf, price: 3452
name: kenfs, price: 979
使用sorted按书名排序
sbooks = sorted(books, key = lambda x : x.name)
输出结果:
name: dfw, price: 435
name: ed, price: 123
name: gwert, price: 56
name: hkjhi, price: 12
name: indf, price: 123
name: kenfs, price: 979
name: kjsdf, price: 3452
name: rgsd, price: 23
name: ydfg, price: 674
name: zert, price: 12
按书价排序
tbooks.sort(key = lambda x: x.price)
print(tbooks) #这里会输出按书价升序排序的序列
对多个关键词自定义排序,方法也比较简单, 对单个关键词排序, 我们lambda表达式中给key返回单个关键词, 那么对多个关键字排序, 只需要在lambda表达式中返回一个元组即可, sorted()会首先按第一个元素排序, 然后第二个, 依次类推…
下面看看对书本先按价格排序,如果价格相同,那么再按书名字典序排序的示例:
sbooks = sorted(books, key = lambda x : (x.price, x.name))
for x in sbooks:
print(x)
输出结果:
name: hkjhi, price: 12
name: zert, price: 12
name: rgsd, price: 23
name: gwert, price: 56
name: ed, price: 123
name: indf, price: 123
name: dfw, price: 435
name: ydfg, price: 674
name: kenfs, price: 979
name: kjsdf, price: 3452
对于按多个关键词排序, 如果我们想对其中某些关键词按降序排序怎么办呢因为默认都是升序的, 我查了很久才搞定这问题, 但实际上方法很简单, 直接在lambda表式中在需要降序排序的关键词前面加一个负号(-)就可以了
同样对于上述例子, 如果想先按姓名长度排序,如果长度相同,那么再按价格降序排序,使用下面的方法即可
sbooks = sorted(books, key = lambda x : (len(x.name), -x.price))
输出结果:
name: ed, price: 123
name: dfw, price: 435
name: ydfg, price: 674
name: indf, price: 123
name: rgsd, price: 23
name: zert, price: 12
name: kjsdf, price: 3452
name: kenfs, price: 979
name: gwert, price: 56
name: hkjhi, price: 12
对象排序我们还可以使用attrgetter(key1, key2…)指派排序关键词, 使用前导入”operator”. 下面这例子先按books中的name属性排序,相同按price排序
import operator
sbooks = sorted(books, key = operator.attrgetter("name", "price"))