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)之前。

 

posted @ 2020-08-28 22:16  leungqingyun  阅读(549)  评论(0编辑  收藏  举报