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

我知道有几个问题是这样命名的,但它们似乎对我不起作用。

我有一个列表的列表,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 + + ,这与我的回调函数的任何想法相矛盾。如何使用自定义函数对列表进行排序?

剪辑 我找到了我的错误。在创建原始列表的链中,一个函数没有返回任何内容,但使用了返回值。抱歉打扰了

202796 次浏览
>>> 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]]

上面的方法很有效。你在做什么不同的事情吗?

注意,您的 key 函数只是 sum; 不需要显式地编写它。

另外,比较函数也不正确。它需要返回 -1、0或1,而不是您所拥有的布尔值。正确的比较函数应该是:

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


# Calling
list.sort(key=compare)

您需要稍微修改一下 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]]

作品:)

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

通常,您希望使用内置的 sorted()函数,该函数采用自定义比较器作为参数。我们需要注意的事实是,在 Python3中,参数名称和语义已经发生了变化。

自定义比较器是如何工作的

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

  • 返回一个负值(< 0)时,左边的项目应该排序 之前右边的项目
  • 返回一个正值(> 0)时,左边的项目应该排序 之后右边的项目
  • 返回 0时,左右两个项目有相同的重量,应订购“同等”没有优先次序

在 OP 问题的特殊情况下,可以使用以下自定义比较函数:

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

使用负运算是一个巧妙的技巧,因为当左侧 item1的权重大于右侧 item2的权重时,它会向正值屈服。因此 item1将被排序为 之后 item2

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

在 Python 2中调用 sort ()

sorted(mylist, cmp=compare)

或:

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

在 Python 3中调用 sort ()

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)))

我无意中发现了这个线程,用比较器函数对列表列表进行排序。对于那些刚接触 Python 或者有 c + + 背景的人来说。我们想要复制使用回调函数,比如 c + + 。我尝试使用 sort ()函数来实现这一点。

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

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]]

查看它的一个简单方法是,Python 中的 sorted()(或 list.sort())函数每次操作一个键。它通过单次传递列表元素来构建密钥列表。然后,它确定哪个键大于或小于,并将它们按正确的顺序排列。

所以我发现,解决办法就是制作一把能够给出正确顺序的钥匙。在这里,Python 可以使用键作为 strtuple。这不像其他例子那样需要 functools模块:

# task: sort the list of strings, such that items listed as '_fw' come before '_bw'
foolist = ['Goo_fw', 'Goo_bw', 'Foo_fw', 'Foo_bw', 'Boo_fw', 'Boo_bw']


def sortfoo(s):
s1, s2 = s.split('_')
r = 1 if s2 == 'fw' else 2     # forces 'fw' to come before 'bw'
return (r, s1)                 # order first by 'fw'/'bw', then by name


foolist.sort(key=sortfoo)          # sorts foolist inplace


print(foolist)
# prints:
# ['Boo_fw', 'Foo_fw', 'Goo_fw', 'Boo_bw', 'Foo_bw', 'Goo_bw']

这是因为元组是用于排序的法定密钥。这可以根据需要进行自定义,其中不同的排序元素按照排序的重要性顺序简单地堆叠到这个元组中。

为了 python3x

arr = [1, 33, 23, 56, 9]


def compare_func(x, y):
return x - y

1. 在比较函数中使用 arr.sort

arr.sort(key=cmp_to_key(compare_func))

2. 使用 sorted获得 新名单

new_list = sorted(arr, key=cmp_to_key(lambda x, y: x - y)))

3. 在 lambda 中使用 arr.sort

arr.sort(key=cmp_to_key(lambda x, y: x - y))