《Python数据科学指南》——1.23 采用键排序

    xiaoxiao2024-01-22  162

    本节书摘来自异步社区《Python数据科学指南》一书中的第1章,第1.23节,作者[印度] Gopi Subramanian ,方延风 刘丹 译,更多章节内容可以访问云栖社区“异步社区”公众号查看。

    1.23 采用键排序

    到目前为止,我们的示例都是采用元素对列表或其他序列进行排序,现在我们来试试对它们采用键排序。在前面的那些示例中,元素即是键。而在真实场景中,记录的复杂度要高得多,一条记录包含了多个列,我们有时需要对其中一个或多个列进行排序。我们通过对一个元组的列表进行排序来阐述,并将之推广到其他的序列类型。

    1.23.1 准备工作

    本示例中,一个单独的元组表示一个人的个人记录,包括名字、ID、年龄等。我们来编写一段对不同的域进行排序的代码。

    1.23.2 操作方法

    我们使用列表和元组来编写一个记录类的结构,并使用这些数据演示如何采用键进行排序。

    # 1.首先创建一个元组组成的列表用来测试排序 employee_records = [ ('joe',1,53),('beck',2,26), \ ('ele',6,32),('neo',3,45), \ ('christ',5,33),('trinity',4,29), \ ] # 2.使用雇员名字进行排序 print sorted(employee_records,key=lambda emp : emp[0]) """ 输出结果如下。 [('beck', 2, 26), ('christ', 5, 33), ('ele', 6, 32), ('joe', 1, 53),\ ('neo', 3, 45), ('trinity', 4, 29)] """ # 3. 使用雇员ID进行排序 print sorted(employee_records,key=lambda emp : emp[1]) """ 输出结果如下。 [('joe', 1, 53), ('beck', 2, 26), ('neo', 3, 45), ('trinity', 4, 29),\ ('christ', 5, 33), ('ele', 6, 32)] """ # 4. 使用雇员年龄进行排序 print sorted(employee_records,key=lambda emp : emp[2]) """

    输出结果如下。

    [('beck', 2, 26), ('trinity', 4, 29), ('ele', 6, 32), ('christ', 5,\ 33), ('neo', 3, 45), ('joe', 1, 53)] """

    1.23.3 工作原理

    在我们的示例中,每条记录有3个域:姓名、ID和年龄。我们使用lambda函数来将我们需要排序的键进行传递。在第2步中,我们将姓名作为键来进行排序。类似地,在第2步和第3步中,都分别采用了ID和年龄作为键,这些不同步骤里的不同输出结果显示了我们想要的排序结果。

    1.23.4 更多内容

    由于键排序十分重要,Python提供了快捷的函数来访问键,而不用自己写lambda函数。operator模块中提供了itemgetter、attrgetter和methodcaller等几个函数。前面排序示例我们可以使用itemgetter来重写,代码如下。

    from operator import itemgetter employee_records = [ ('joe',1,53),('beck',2,26), \ ('ele',6,32),('neo',3,45), \ ('christ',5,33),('trinity',4,29), \ ] print sorted(employee_records,key=itemgetter(0)) """ [('beck', 2, 26), ('christ', 5, 33), ('ele', 6, 32), ('joe', 1, 53),\ ('neo', 3, 45), ('trinity', 4, 29)] """ print sorted(employee_records,key=itemgetter(1)) """ [('joe', 1, 53), ('beck', 2, 26), ('neo', 3, 45), ('trinity', 4, 29),\ ('christ', 5, 33), ('ele', 6, 32)] """ print sorted(employee_records,key=itemgetter(2)) """ [('beck', 2, 26), ('trinity', 4, 29), ('ele', 6, 32), ('christ', 5,\ 33), ('neo', 3, 45), ('joe', 1, 53)] """

    请注意我们不再使用lambda函数,而是采用itemgetter来指定我们用来排序的键。如果需要多级排序,itemgetter可以接收多个用来排序的域。例如,我们先对名字,再对年龄进行排序,那代码如下。

    >>> sorted(employee_records,key=itemgetter(0,1)) [('beck', 2, 26), ('christ', 5, 33), ('ele', 6, 32), ('joe', 1, 53), ('neo', 3, 45), ('trinity', 4, 29)]

    如果可迭代对象里的元素是类对象,则可以用attrgetter和methodcaller轻松搞定。请看如下示例。

    # 将雇员记录封装为类对象 class employee(object): def __init__(self,name,id,age): self.name = name self.id = id self.age = age def pretty_print(self): print self.name,self.id,self.age # 将这些类对象填入列表里 employee_records = [] emp1 = employee('joe',1,53) emp2 = employee('beck',2,26) emp3 = employee('ele',6,32) employee_records.append(emp1) employee_records.append(emp2) employee_records.append(emp3) # 打印输出记录 for emp in employee_records: emp.pretty_print() from operator import attrgetter employee_records_sorted = sorted(employee_ records,key=attrgetter('age')) # 打印输出排序后的记录 for emp in employee_records_sorted: emp.pretty_print()

    构造器使用name、age和ID等3个变量对类进行初始化,类还拥有一个pretty_print方法来输出类对象的各个值。

    接着,把这些类对象填入一个列表。

    employee_records = [] emp1 = employee('joe',1,53) emp2 = employee('beck',2,26) emp3 = employee('ele',6,32) employee_records.append(emp1) employee_records.append(emp2) employee_records.append(emp3)

    现在,我们有一个雇员对象的列表,每个对象中有3个变量:name、ID和age。我们将列表打印输出来观察其顺序。

    joe 1 53 beck 2 26 ele 6 32

    如你所见,你的输入顺序被保留下来了。现在,我们使用attrgetter根据age域来对列表进行排序。

    employee_records_sorted = sorted(employee_ records,key=attrgetter('age'))

    打印输出排序后的列表,结果如下。

    beck 2 26 ele 6 32 joe 1 53

    记录已经被按照年龄进行了排序。

    如果想用类里的某个方法来决定排序方式,我们得使用methodcaller。我们设计一个演示场景:添加一个随机方法,将年龄除以ID。

    class employee(object): def __init__(self,name,id,age): self.name = name self.id = id self.age = age def pretty_print(self): print self.name,self.id,self.age def random_method(self): return self.age / self.id # 填充数据 employee_records = [] emp1 = employee('joe',1,53) emp2 = employee('beck',2,26) emp3 = employee('ele',6,32) employee_records.append(emp1) employee_records.append(emp2) employee_records.append(emp3) from operator import methodcaller employee_records_sorted = sorted(employee_records,key=methodcaller('ra\ ndom_method')) for emp in employee_records_sorted: emp.pretty_print()

    现在我们调用这个方法来进行排序。

    sorted(employee_records,key=methodcaller('random_method'))

    打印输出排序后的列表,结果如下。

    ele 6 32 beck 2 26 joe 1 53 相关资源:敏捷开发V1.0.pptx
    最新回复(0)