简体   繁体   English

如何将其他参数传递给自定义python排序功能

[英]How to pass additional arguments to custom python sorting function

Background: 背景:

I would like to know how I can implement advanced sorting functions that I can pass in as tuple element to the key argument of the python 'sorted' function. 我想知道如何实现高级排序功能,这些功能可以作为元组元素传递给python'sorted'函数的键参数。

Here is an example depicting what I would like to do: 这是一个描述我想做什么的例子:

class Book:

      def __init__(self, name, author, language, cost):
          self.name = name
          self.author = author
          self.language=language
          self.cost = cost


bookList = [list of books]

firstLanguage = "Armenian"
possibleLanguages = ["English", "Spanish", "Armenian", "French", "Chinese", "Swahili"]
possibleLanguages.remove("Armenian")

sortedBookList = sorted(bookList, key=(sortByName,
    sortByFirstLanguage(firstLanguage), sortByLanguages(possibleLanguages) ))

Basically I would like to implement the 'sortByFirstLanguage' and 'sortByLanguages' functions described above so that I can pass them to the python 'sorted' function as the tuple items of the 'key' argument. 基本上,我想实现上述的'sortByFirstLanguage'和'sortByLanguages'函数,以便可以将它们作为'key'参数的元组项传递给python'sorted'函数。 Here is some example code regarding what the custom sort functions should look like: 这是一些有关自定义排序功能应如何的示例代码:

def sortByName(elem):
    return elem.name

def sortByFirstLanguage(elem, firstLanguage):
    if elem.language == firstLanguage:
       return 1
    else:
       return -1


def sortByLanguages(elem, possibleLanguages):
    if elem.language in possibleLanguages:
       return possibleLanguages.index(elem.language)

Addt. 加。 Details: 细节:

  1. I am using python 2.7 我正在使用python 2.7
  2. This problem is actually using Django querysets rather than lists of objects, but for demonstration of purpose, I think a list of objects serves the same purpose. 这个问题实际上是使用Django查询集而不是对象列表,但是出于演示目的,我认为对象列表具有相同的目的。
  3. The goal of this sorting is to sort by a specified language first, then go back && sort the remaining items by their default ordering (list ordering in this case). 排序的目的是先按指定的语言排序,然后再按默认顺序(在这种情况下为列表排序)对其余项进行&&排序。

Question: 题:

How exactly can I tell the 'key' argument to pass in the extra arguments 'firstLanguage' && 'possibleLanguages' to custom sorting functions as I have shown above? 我如何准确地告诉'key'参数将额外的参数'firstLanguage'&&'possibleLanguages'传递给自定义排序函数,如我上面所示?

As Ashish points out in the comments, we first need to combine these functions, since key only accepts a single functions. 正如Ashish在评论中指出的那样,我们首先需要组合这些功能,因为key只接受一个功能。 If we return a sequence (list, tuple) of the function results, Python will do the right thing, only comparing later (farther right) elements if the earlier elements are equal ( source ). 如果我们返回函数结果的序列(列表,元组),Python会做正确的事情,只有在较早的元素相等时才比较较晚的元素( )。

I know of a couple ways to do this. 我知道有几种方法可以做到这一点。

Using lambdas: 使用lambda:

sortedBookList = sorted(
    bookList, 
    key=lambda elem: (sortByName(elem), 
                      sortByFirstLanguage(elem, firstLanguage), 
                      sortByLanguages(elem, possibleLanguages)))

Using higher-order functions: 使用高阶函数:

def key_combiner(*keyfuncs):
  def helper(elem):
    return [keyfunc(elem) for keyfunc in keyfuncs]
  return helper

def sortByFirstLanguage(firstLanguage):
  def helper(elem):
    return elem.language == firstLanguage  # True > False
  return helper

def sortByLanguages(possibleLanguages):
  def helper(elem):
    if elem.language in possibleLanguages:
       return possibleLanguages.index(elem.language)
  return helper

sortedBookList = sorted(bookList,
                        key=key_combiner(sortByName, 
                                         sortByFirstLanguage(firstLanguage), 
                                         sortByLanguages(possibleLanguages))

Lambdas seem cleanest to me, so that's probably what I'd use. Lambda对我来说似乎是最干净的,所以这可能就是我要使用的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM