在Python中使用自定义比较函数对列表进行排序

时间:2011-03-06 20:05:38

标签: python list sorting callback

我知道有几个问题就像这样,但我似乎无法得到他们的工作答案。

我有一个列表列表,50次5个元素。现在我想通过对每个元素应用自定义比较函数来对此列表进行排序。此函数计算列表的适合度,元素应按顺序排序。我创建了两个函数,比较和适应性:

def compare(item1, item2):
    return (fitness(item1) < fitness(item2))

def fitness(item):
    return item[0]+item[1]+item[2]+item[3]+item[4]

然后我试着通过以下方式打电话给他们:

sorted(mylist, cmp=compare)

sorted(mylist, key=fitness)

sorted(mylist, cmp=compare, key=fitness)

sorted(mylist, cmp=lambda x,y: compare(x,y))

我也尝试使用相同的参数list.sort()。但无论如何,函数不会将列表作为参数而是None。我不知道为什么会这样,主要来自C ++,这与我的回调函数的任何想法都是矛盾的。如何使用自定义函数对此列表进行排序?

修改 我发现了自己的错误。在创建原始列表的链中,除了使用返回值之外,一个函数没有返回任何内容。很抱歉打扰

5 个答案:

答案 0 :(得分:62)

此外,您的比较功能不正确。它需要返回-1,0或1,而不是布尔值。正确的比较函数是:

def compare(item1, item2):
    if fitness(item1) < fitness(item2):
        return -1
    elif fitness(item1) > fitness(item2):
        return 1
    else:
        return 0

答案 1 :(得分:26)

>>> l = [list(range(i, i+4)) for i in range(10,1,-1)]
>>> l
[[10, 11, 12, 13], [9, 10, 11, 12], [8, 9, 10, 11], [7, 8, 9, 10], [6, 7, 8, 9], [5, 6, 7, 8], [4, 5, 6, 7], [3, 4, 5, 6], [2, 3, 4, 5]]
>>> sorted(l, key=sum)
[[2, 3, 4, 5], [3, 4, 5, 6], [4, 5, 6, 7], [5, 6, 7, 8], [6, 7, 8, 9], [7, 8, 9, 10], [8, 9, 10, 11], [9, 10, 11, 12], [10, 11, 12, 13]]

以上作品。你在做些不同的事吗?

请注意,您的关键功能只是sum;没有必要明确地写出来。

答案 2 :(得分:12)

您需要稍微修改一下compare功能,然后使用functools.cmp_to_key将其传递给sorted。示例代码:

import functools

lst = [list(range(i, i+5)) for i in range(5, 1, -1)]

def fitness(item):
    return item[0]+item[1]+item[2]+item[3]+item[4]
def compare(item1, item2):
    return fitness(item1) - fitness(item2)

sorted(lst, key=functools.cmp_to_key(compare))

输出:

[[2, 3, 4, 5, 6], [3, 4, 5, 6, 7], [4, 5, 6, 7, 8], [5, 6, 7, 8, 9]]

工作:)

答案 3 :(得分:1)

我偶然发现了这个线程,通过比较器函数对列表列表进行排序。对于刚接触 Python 或来自 C++ 背景的任何人。我们想复制到这里像 c++ 一样使用回调函数。我用 sorted() 函数试过这个。

例如:如果我们想根据标记(升序)对这个列表进行排序,如果标记相等,则名称(升序)

students= [['Harry', 37.21], ['Berry', 37.21], ['Tina', 37.2], ['Akriti', 41.0], ['Harsh', 39.0]]

def compare(e):
  return (e[1],e[0])

students = sorted(students,key=compare)

排序后:

[['Tina', 37.2], ['Berry', 37.21], ['Harry', 37.21], ['Harsh', 39.0], ['Akriti', 41.0]]

答案 4 :(得分:0)

由于OP要求使用自定义比较功能(这也是导致我提出这个问题的原因),所以我想在这里给出可靠的答案:

通常,您要使用内置的sorted()函数,该函数将自定义比较器作为其参数。我们需要注意以下事实:在Python 3中,参数名称和语义已更改。

自定义比较器的工作方式

在提供自定义比较器时,通常应返回遵循以下模式的整数/浮点值(与大多数其他编程语言和框架一样):

  • 当左侧项目应该排在之前右侧项目
  • 时,返回负值(< 0
  • 当左项应该排在右项之后
  • 时,返回正值(> 0
  • 当左一项和右一项具有相同的权重时应返回0,并且应“均等”地排序而没有优先级

对于OP的特定问题,可以使用以下自定义比较功能:

def compare(item1, item2):
    return fitness(item1) - fitness(item2)

使用减号运算是一个很巧妙的技巧,因为当左项(这里:item1)的权重大于右项(这里:item2的权重时,它会产生正值。因此,item1将在item2之后排序。

如果要反转排序顺序,只需反转减法:return fitness(item2) - fitness(item1)

在Python 2中调用sorted()

sorted(mylist, key=cmp(compare))

或:

sorted(mylist, cmp=lambda item1, item2: fitness(item1) - fitness(item2))

在Python 3中调用sorted()

from functools import cmp_to_key
sorted(mylist, key=cmp_to_key(compare))

或:

from functools import cmp_to_key
sorted(mylist, key=cmp_to_key(lambda item1, item2: fitness(item1) - fitness(item2)))