【问题标题】:How do operator.itemgetter() and sort() work?operator.itemgetter() 和 sort() 是如何工作的?
【发布时间】:2013-09-06 21:20:06
【问题描述】:

我有以下代码:

# initialize
a = []

# create the table (name, age, job)
a.append(["Nick", 30, "Doctor"])
a.append(["John",  8, "Student"])
a.append(["Paul", 22, "Car Dealer"])
a.append(["Mark", 66, "Retired"])    

# sort the table by age
import operator
a.sort(key=operator.itemgetter(1))    

# print the table
print(a)

它创建一个 4x3 表,然后按年龄对其进行排序。我的问题是,key=operator.itemgetter(1) 到底是做什么的? operator.itemgetter 函数是否返回项目的值?为什么我不能在那里输入key=a[x][1] 之类的东西?或者我可以吗?运算符如何打印表单的某个值,例如3x2,即22

  1. Python 究竟是如何对表格进行排序的?我可以对其进行反向排序吗?

  2. 如何根据第一年龄等两列对它进行排序,然后如果年龄是相同的 b 名称?

  3. 没有operator怎么办?

【问题讨论】:

标签: python sorting operator-keyword


【解决方案1】:

看起来你对所有这些东西有点困惑。

operator 是一个内置模块,提供了一组方便的操作符。简而言之,operator.itemgetter(n) 构造了一个可调用对象,该可调用对象假定一个可迭代对象(例如列表、元组、集合)作为输入,并从中获取第 n 个元素。

所以,你不能在那里使用key=a[x][1],因为python 不知道x 是什么。相反,您可以使用 lambda 函数(elem 只是一个变量名,没有任何魔法):

a.sort(key=lambda elem: elem[1])

或者只是一个普通的函数:

def get_second_elem(iterable):
    return iterable[1]

a.sort(key=get_second_elem)

所以,这里有一个重要的说明:在python中函数是first-class citizens,所以你可以将它们作为参数传递给其他函数。

其他问题:

  1. 是的,你可以反向排序,只需添加reverse=Truea.sort(key=..., reverse=True)
  2. 要按多列排序,您可以使用 itemgetter 和多个索引:operator.itemgetter(1,2),或使用 lambda:lambda elem: (elem[1], elem[2])。这样,可以为列表中的每个项目动态构建可迭代对象,然后按字典顺序(?)相互比较(比较第一个元素,如果相等 - 比较第二个元素等)
  3. 您可以使用a[2,1] 获取[3,2] 处的值(索引从零开始)。使用运算符...这是可能的,但不如索引那么干净。

详情请参阅文档:

  1. operator.itemgetter explained
  2. Sorting list by custom key in Python

【讨论】:

  • 你将如何排序由一列反转而不是由另一列反转?
  • operator.itemgetter(n) 似乎不适用于setdict (如果n 是有效密钥而不是一些int 你来了,它可能与dict 一起使用与)。
  • @Vim According to docs,对于 dict 它应该适用于任何可散列值。 itemgetter(n) 表示它将尝试执行 dict.__getitem__ 查找,这(除非您实际上没有使用 dict,而是扩展 dict 并覆盖 getitem 的自定义类)相当于 dict[n] - 如果字典中没有n 键,它显然会失败。对于您不确定是否存在密钥的字典,您可能想要坚持使用 lambda key: dict.get(key, None) 或类似的东西。示例:ideone.com/PJk8vd
  • @yayitswei 如果一列是数字,则使用lambda row: (row.one_thing, -row.number_thing),如果您想通过one_thing 反转,则提供reverse=True。如果您没有像这样简单的数字选项,您将不得不进行更多操作。
  • @yahyitswei 是的,请在此处查看 itemgetter 排序解决方案以了解多列的不同反向参数,然后您需要连续多个步骤安排排序:stackoverflow.com/questions/14466068/…
【解决方案2】:

给 Python 初学者的答案

简单来说:

  1. sortkey= 参数需要一个键函数(应用于要排序的对象)而不是单个键 和李>
  2. 这正是operator.itemgetter(1) 将为您提供的:一个函数,它从一个类似列表的对象中获取第一个项目。

(更准确地说,那些是 callables,而不是函数,但这是一个经常可以忽略的区别。)

【讨论】:

  • 谢谢 - 作为一个仍在学习的 Python 程序员,这就是我想要了解正在发生的事情。我不清楚我的代码中的 ".sort(key = attrgetter("index"))" 是否将带有参数 "index" 的 FUNCTION attrgetter() 发送到 Sort() 函数;我以为它是用 C 和其他语言发送结果。
  • @Locane:不,这不是正在发生的事情。 attrgetter 将为您构造一个适当的函数并返回它。它正在发送“结果”。只有那个结果才是一个函数。
【解决方案3】:

你问了很多问题,你可以通过reading the documentation 自己回答,所以我会给你一个一般性的建议:阅读它并在 python shell 中进行实验。你会看到itemgetter 返回一个可调用对象:

>>> func = operator.itemgetter(1)
>>> func(a)
['Paul', 22, 'Car Dealer']
>>> func(a[0])
8

要以不同的方式执行此操作,您可以使用lambda

a.sort(key=lambda x: x[1])

然后反转它:

a.sort(key=operator.itemgetter(1), reverse=True)

按多列排序:

a.sort(key=operator.itemgetter(1,2))

请参阅sorting How To

【讨论】:

    【解决方案4】:
    #sorting first by age then profession,you can change it in function "fun".
    a = []
    
    def fun(v):
        return (v[1],v[2])
    
    # create the table (name, age, job)
    a.append(["Nick", 30, "Doctor"])
    a.append(["John",  8, "Student"])
    a.append(["Paul",  8,"Car Dealer"])
    a.append(["Mark", 66, "Retired"])
    
    a.sort(key=fun)
    
    
    print a
    

    【讨论】:

    • 此方案不使用操作符
    【解决方案5】:
    a = []
    a.append(["Nick", 30, "Doctor"])
    a.append(["John",  8, "Student"])
    a.append(["Paul",  8,"Car Dealer"])
    a.append(["Mark", 66, "Retired"])
    print a
    
    [['Nick', 30, 'Doctor'], ['John', 8, 'Student'], ['Paul', 8, 'Car Dealer'], ['Mark', 66, 'Retired']]
    
    def _cmp(a,b):     
    
        if a[1]<b[1]:
            return -1
        elif a[1]>b[1]:
            return 1
        else:
            return 0
    
    sorted(a,cmp=_cmp)
    
    [['John', 8, 'Student'], ['Paul', 8, 'Car Dealer'], ['Nick', 30, 'Doctor'], ['Mark', 66, 'Retired']]
    
    def _key(list_ele):
    
        return list_ele[1]
    
    sorted(a,key=_key)
    
    [['John', 8, 'Student'], ['Paul', 8, 'Car Dealer'], ['Nick', 30, 'Doctor'], ['Mark', 66, 'Retired']]
    >>> 
    

    【讨论】:

      【解决方案6】:

      使用用户定义函数对数组进行排序的最简单方法是使用 Functools 中的 cmp_to_key。 这是一个示例代码:

      from functools import cmp_to_key
      
      def mine(x,y):
          if(x[1]!=y[1]): return x[1]>y[1]
          else: return x[0]>y[0]
          
      a = []
      a.append(["Nick", 30, "Doctor"])
      a.append(["John",  8, "Student"])
      a.append(["Paul", 22, "Car Dealer"])
      a.append(["Mark", 66, "Retired"])  
      
      def mine(a,b):
          if a[1] > b[1]:
              return 1
          elif a[1] < b[1]:
              return -1
          else:
              if a[0] > b[0]:
                  return 1
              else:
                  return 0
                           
      print(sorted(a,key = cmp_to_key(mine)))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-08-09
        • 1970-01-01
        • 2015-10-09
        • 1970-01-01
        • 2020-04-04
        • 2022-09-25
        • 2013-02-20
        相关资源
        最近更新 更多