Python列表 sort排序单独详解
Python列表有一个内置的sort()方法,用于修改列表的位置,以及一个sorted()内置函数,用于从一个可迭代函数构建一个新的已排序列表。
简单的升序排序非常简单——只需调用sorted()函数。它返回一个新的排序列表:
old_list=[3,2,4,1,5] new_list=sorted(old_list) # [1,2,3,4,5]
您还可以使用列表的list.sort()方法。它就地修改列表(并返回None以避免混淆)。通常它不如sorted()方便; 但是如果您不需要原始列表,它的效率会稍微高一些。
a=[3,2,4,1,5] a.sort() # a=[1,2,3,4,5]
另一个区别是list.sort()方法仅为列表定义。相反,sorted()函数接受任何可迭代的函数。
sorted({1: 'D', 2: 'B', 3: 'B', 4: 'E', 5: 'A'}) # [1,2,3,4,5] 只针对key进行排序
Key Functions
从Python 2.4开始,list.sort()和sorted()都添加了一个关键参数,以指定在进行比较之前对每个列表元素调用的函数。
string="This is a test string from Andrew" li=string.split() # li=['This', 'is', 'a', 'test', 'string', 'from', 'Andrew'] new_li=sorted(li,key=str.lower) # new_li=['a', 'Andrew', 'from', 'is', 'string', 'test', 'This']
key参数的值应该是一个函数,它接受单个参数并返回一个用于排序目的的键。这种技术速度很快,因为对于每个输入记录,键函数只调用一次。
student_tuples =[ ('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10), ] res=sorted(student_tuples, key=lambda student: student[2]) # res= [('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)) def weighted_grade(self): return 'CBA'.index(self.grade) / float(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)]
Operator Module Functions
上面所示的 键-函数 模式非常常见,因此Python提供了方便的函数来使访问函数更简单、更快。运算符模块有itemgetter、attrgetter和start(在Python 2.6中有一个methodcaller函数)
attrgetter 使用
from operator import itemgetter, attrgetter, methodcaller 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)) def weighted_grade(self): return 'CBA'.index(self.grade) / float(self.age) student_objects = [ Student('john', 'A', 15), Student('jane', 'B', 12), Student('dave', 'B', 10), ] res=sorted(student_objects, key=attrgetter('age')) # res= [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
itemgetter 使用
from operator import itemgetter, attrgetter, methodcaller tuples = [ ('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10), ] res=sorted(tuples, key=itemgetter(2)) # res= [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)
methodcaller 使用
from operator import itemgetter, attrgetter, methodcaller 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)) def weighted_grade(self): return 'CBA'.index(self.grade) / float(self.age) student_objects = [ Student('john', 'A', 15), Student('jane', 'B', 12), Student('dave', 'B', 10), ] res= sorted(student_objects, key=methodcaller('weighted_grade')) # res= [('jane', 'B', 12), ('dave', 'B', 10), ('john', 'A', 15)]
sort()和sorted()接受一个具有布尔值的反向参数。用于标记降序排序。例如,要以反向年龄顺序获取学生数据:
sorted(student_objects, key=attrgetter('age'), reverse=True)
排序稳定性和复杂排序
从Python 2.2开始,排序就被保证是稳定的。这意味着,当多个记录具有相同的键时,将保留它们的原始顺序。
from operator import itemgetter, attrgetter, methodcaller data = [('red', 1), ('blue', 1), ('red', 2), ('blue', 2)] res=sorted(data, key=itemgetter(0)) # res= [('blue', 1), ('blue', 2), ('red', 1), ('red', 2)]
# 请注意'blue'的两条记录是如何保持它们原来的顺序的,这样('blue', 1)就可以保证在('blue', 2)之前。