1、sort 与 sorted 区别
① sort 是应用在 list 上的方法,属于列表的成员方法,sorted 可以对所有可迭代的对象进行排序操作。
② list 的 sort 方法返回的是对已经存在的列表进行操作,而内建函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作。
③ sort使用方法为ls.sort(),而sorted使用方法为sorted(ls)。
通过代码,简单解释sort()与sorted()的区别:
2、sort()的理解使用
sort() 函数用于对原列表进行排序,如果指定参数,则使用比较函数指定的比较函数。
语法如下:
list.sort(cmp=None, key=None, reverse=False)
参数:
cmp – 可选参数,如果指定了该参数会使用该参数的方法进行排序。
key – 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
reverse – 排序规则,reverse = True 降序, reverse = False 升序(默认)。
返回值:
该函数没有返回值,但会对数组/列表进行排序
a = [1, 3, 4, 2]
# 1.一般调用
a.sort() # 调用1,无返回值,a=[1, 2, 3, 4]
a.sort(reverse=True) # 逆序, a=[4, 3, 2, 1]
b = sorted(a) # 调用2,有返回值, b=[1, 2, 3, 4]
# 2.通过指定列表中的元素排序输出列表
# 获取列表的第二个元素
def takeSecond(elem):
return elem[1]
# 列表
random = [(2, 2), (3, 4), (4, 1), (1, 3)]
# 指定第二个元素排序
random.sort(key=takeSecond) # 按列表每个元组中第二位元素的升序排序整个数组
# 输出类别
print(random) # [(4, 1), (2, 2), (1, 3), (3, 4)]
需要注意的地方:
① cmp作为sort()参数使用(python2中使用,python3已弃用)
② python3中也取消了函数传入机制,可以构造排序函数递给key实现。
示例:
>>> cmp(42,32)
1
>>> cmp(99,100)
-1
>>> cmp(10,10)
0
>>> numbers = [5,2,9,7]
>>> numbers.sort()
>>> numbers.sort(cmp) # 通过调用cmp(x,y)来排序,与不传入cmp参数时效果一样(结果相同,但实际执行流程不同)
>>> numbers
[2,5,7,9]
或者自定义函数传入:
numbers = [5, 2, 9, 7]
def reverse_numbers(x, y):
return y - x
numbers.sort(cmp = reverse_numbers) # 逆序,numbers=[9,7,5,2]
# 上述用lambda匿名函数也可以写成:
numbers.sort(lambda x, y: y-x) # numbers=[9,7,5,2]
算法中的应用:
例:把数组排成最小的数
输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。
class Solution:
def PrintMinNumber(self, numbers):
# write code here
if not len(numbers):
return ""
arr = [str(x) for x in numbers]
arr.sort(lambda x,y:cmp(x+y,y+x)) # 让x和y及y和x拼接后的字符串进行大小比较,若x+y<y+x,则x,y的前后位置不变;反之x,y交换位置(y提到x之前)。
return int("".join(arr))
3、sorted()的理解使用
sorted() 函数对所有可迭代的对象进行排序操作
语法如下:
sorted(iterable, cmp=None, key=None, reverse=False)
参数说明:
iterable – 可迭代对象。
cmp – 比较的函数,这个具有两个参数,参数的值都是从可迭代对象中取出,此函数必须遵守的规则为,大于则返回1,小于则返回-1,等于则返回0。(一般省略)
key – 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
常用的用来作为参数key的函数有 lambda函数和operator.itemgetter()
尤其是列表元素为多维数据时,需要key来选取按哪一位数据来进行排序
reverse – 排序规则,reverse = True 降序 , reverse = False 升序(默认)。
返回值
返回重新排序的列表;
需要注意:列表的元素可以是多样的,返回列表的形式与输入列表的形式一致。
元组和集合同样可以使用sorted()函数!
值得注意的是:
即使输入的是一个集合和元组,输出结果仍然是一个列表,因为sorted()函数根据定义会返回一个新列表,如果返回的对象需要匹配输入类型,则可以将其转化为新类型。
如果试图将结果列表转换回集合类型,请注意,按照定义而言,集合是无序的。
1)一般用法
当元素为一维数字或字母时,结果返回一个新的列表,其中元素按升序或降序排列(根据reverse参数来决定)。
list = [1, 5, 7, 2, 4]
print(sorted(list))
输出:
[1, 2, 4, 5, 7]
list = ['d', 'c', 'f', 'a', 'z']
print(sorted(list))
输出:
['a', 'c', 'd', 'f', 'z']
list = ['vz', '1bf', 'gc', 'ak', '2qz']#若为字符串,则跟据第一位的数字-字母顺序来排列
print(sorted(list))
输出:
['1bf', '2qz', 'ak', 'gc', 'vz']
2)各类使用举例
例1:正序排序
a = [20, 5, 6, 7, 8, 1]
res1 = sorted(a) # 正序排序
print(res1)
输出: [1, 5, 6, 7, 8, 20]
例2:逆序排序
a = [20, 5, 6, 7, 8, 1]
res1 = sorted(a, reverse=True) # 逆序排序
print(res1)
输出: [20, 8, 7, 6, 5, 1]
例3:根据字符长短进行排序
lst = ['ccc', 'aaaaaa', 'ff', 'd']
def func(n):
return len(n)
print(sorted(lst, key=func))
输出:[‘d’, ‘ff’, ‘ccc’, ‘aaaaaa’]
例4:和lambda()函数配合使用
lst = ['ccc', 'aaaaaa', 'ff', 'd']
# 根据字符长短进行排序
print(sorted(lst, key=lambda n: len(n)))
输出:[‘d’, ‘ff’, ‘ccc’, ‘aaaaaa’]
例5:对列表中的元素进行排序,key比较
list1 = [('david', 90), ('mary', 90), ('sara', 80), ('lily', 95)]
L1 = sorted(list1, key=lambda x: x[0])
L2 = sorted(list1, key=lambda x: x[1])
print(L1)
print(L2)
输出:
[('david', 90), ('lily', 95), ('mary', 90), ('sara', 80)]
[('sara', 80), ('david', 90), ('mary', 90), ('lily', 95)]
例6:sorted() 用于字典dictionary
字典排序
① 返回的是排序后的key
dict = {1: 'A', 3: 'C', 2: 'B'}
res1 = sorted(dict)
print(res1)
输出: [1, 2, 3]
② 对字典进行排序,需将字典通过items()转换为元组列表
di={'zhang':4,'pan':7,'wang':4,'li':2,'hu':2}
di.items()
输出:
dict_items([(‘zhang’, 4), (‘pan’, 7), (‘wang’, 4), (‘li’, 2), (‘hu’, 2)])
③ sorted()函数默认对字典的key值进行排序
sorted(di.items())
输出:[(‘hu’, 2), (‘li’, 2), (‘pan’, 7), (‘wang’, 4), (‘zhang’, 4)]
sorted(di.items(),reverse=True)
输出:[(‘zhang’, 4), (‘wang’, 4), (‘pan’, 7), (‘li’, 2), (‘hu’, 2)]
④ 如果想要对字典的value值进行排序,可以设置key参数
sorted(di.items(),reverse=True,key=lambda x:x[1])
输出:[(‘pan’, 7), (‘zhang’, 4), (‘wang’, 4), (‘li’, 2), (‘hu’, 2)]
⑤ 嵌套排序
先对字典的value值进行降序排序,value值相同,对相同value值的key值进行降序排序。
sorted(sorted(di.items(),reverse=True,key=lambda x:x[0]),reverse=True,key=lambda item:item[1])
输出:[(‘pan’, 7), (‘zhang’, 4), (‘wang’, 4), (‘li’, 2), (‘hu’, 2)]
3)sorted()函数四种重要的特性
1)sorted()函数不需要定义,它是一个内置函数,可以在标准的Python安装中使用。
2)在没有额外的参数的情况下,sorted()函数按照升序对值进行排列,也就是按照从小到大的顺序。
3)原始的numbers不会改变,因为sorted()函数提供了一个新的有序的输出结果,并且不改变原始值的顺序。
4)当sorted()函数被调用时,它会提供一个有序的列表作为返回值。
最后一点意味着列表可以使用sorted()函数,并且输出结果可以立刻赋值给一个变量。
4、sort()和sorted()高级排序技巧(key的使用)
1)排序基础
简单的升序排序只需要调用sorted()方法,它返回一个新的list,新的list的元素基于小于运算符(lt)来排序。
>>> sorted([5, 2, 3, 1, 4])
[1, 2, 3, 4, 5]
也可以使用list.sort()方法来排序,此时list本身将被修改,通常这种方法不如sorted()方便,但如果你不需要保留原来的list,这种方法更有效。
>>> a = [5, 2, 3, 1, 4]
>>> a.sort()
>>> a
[1, 2, 3, 4, 5]
另一个不同就是list.sort()方法仅被定义在list中,相反地sorted()方法对所有的可迭代序列都有效。
>>> sorted({1: 'D', 2: 'B', 3: 'B', 4: 'E', 5: 'A'})
[1, 2, 3, 4, 5]
2)key参数/函数
例如通过key指定的函数来忽略字符串的大小写:
>>> sorted("This is a test string from Andrew".split(), key=str.lower)
['a', 'Andrew', 'from', 'is', 'string', 'test', 'This']
key参数的值为一个函数,此函数只有一个参数且返回一个值用来进行比较。
更广泛的使用情况是用复杂对象的某些值来对复杂对象的序列排序,例如
>>> student_tuples = [
('john', 'A', 15),
('jane', 'B', 12),
('dave', 'B', 10),
]
>>> sorted(student_tuples, key=lambda student: student[2]) # sort by age
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
同样的技术对拥有命名属性的复杂对象也适用
>>> class Student:
def __init__(self, name, grade, age):
self.name = name
self.grade = grade
self.age = age
def __repr__(self):
return repr((self.name, self.grade, self.age))
>>> student_objects = [
Student('john', 'A', 15),
Student('jane', 'B', 12),
Student('dave', 'B', 10),
]
>>> sorted(student_objects, key=lambda student: student.age) # sort by age
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
3)Operator 模块函数
operator模块有itemgetter,attrgetter,从2.6开始还增加了methodcaller方法。
>>> from operator import itemgetter, attrgetter
>>> sorted(student_tuples, key=itemgetter(2))
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
>>> sorted(student_objects, key=attrgetter('age'))
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
operator模块还允许多级的排序,例如,先以grade,然后再以age来排序:
代码如下:
```python
>>> sorted(student_tuples, key=itemgetter(1,2))
[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]
>>> sorted(student_objects, key=attrgetter('grade', 'age'))
[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]
4)升序和降序
list.sort()和sorted()都接受一个参数reverse(True or False)来表示升序或降序排序。
例如对上面的student降序排序
>>> sorted(student_tuples, key=itemgetter(2), reverse=True)
[('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
>>> sorted(student_objects, key=attrgetter('age'), reverse=True)
[('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
5)排序的稳定性和复杂排序
多个元素如果有相同的key,则排序前后他们的先后顺序不变。
>>> data = [('red', 1), ('blue', 1), ('red', 2), ('blue', 2)]
>>> sorted(data, key=itemgetter(0))
[('blue', 1), ('blue', 2), ('red', 1), ('red', 2)]
注意在排序后’blue’的顺序被保持了,即’blue’, 1在’blue’, 2的前面。
更复杂的你可以构建多个步骤来进行更复杂的排序,例如对student数据先以grade降序排列,然后再以age升序排列。
>>> s = sorted(student_objects, key=attrgetter('age')) # sort on secondary key
>>> sorted(s, key=attrgetter('grade'), reverse=True) # now sort on primary key, descending
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]