将函数传递给排序函数的键

时间:2017-07-14 12:29:12

标签: python list python-3.x sorting

我有一个清单

moveTo()

我想根据特定情况对其进行排序。我想使用一个逻辑,每当lis = [ [0, 1], [1, -1], [1, 0] ] 等于lis[i][0]时,交换元素。像

这样的东西

在上面的列表中,第二和第三个元素是lis[i + 1][0][1, -1],其中[1, 0] == lis[i][0]。所以我会交换它,以便我的新列表变为

lis[i + 1][0]

这是我的功能:

lis = [ [0, 1], [1, 0], [1, -1] ]

我想将此函数传递给列表的def sortList(lis3): for i in range(0, len(lis3) - 1): for j in range(i + 1, len(lis3)): if lis3[i][0] == lis3[j][0]: lis3[i], lis3[j] = lis3[j], lis3[i] 方法,以便根据此逻辑进行排序:

我尝试过这样做但不起作用:

sort

如何在lis.sort(key=sortList) 方法中使用此功能?

4 个答案:

答案 0 :(得分:2)

使用list.sortsorted无法使其正常工作。问题是这些函数背后的排序算法并不能保证哪些元素被比较(它只是说结果将被排序)。要使list.sortsorted可靠地运作,您需要key key,而您的功能无法提供。{/ p>

key也应该是一个将一个元素转换为"应该比较的属性"的函数,它确实将列表的每个元素传递给sort函数而不是总列表(实际上在CPython中,当你{{1}}时,列表是空的,所以它根本无法工作。

答案 1 :(得分:1)

执行此排序的一种方法是对cmp使用sorted参数(对Python 3使用functools.cmp_to_key)并在两个子列表的索引0处的项目比较时返回-1等于或等于零。这假设物品是成对的并且是连续的,所以它不是一个详尽的排序,只是一种交换你的物品的hackish方式:

lis = [ [0, 1], [1, -1], [1, 0], [2, 5], [2, 6]]

print sorted(lis, cmp=lambda x, y: -1 if x[0]==y[0] else 0)
# [[0, 1], [1, 0], [1, -1], [2, 6], [2, 5]]

但是,当索引0处的两个以上项目具有相同值或项目不连续时,排序会变为不明确

OTOH,您可以循环浏览列表并交换符合条件的成对连续项目。无需应用排序!

答案 2 :(得分:1)

正如在其他答案中已经说过的那样,使sorted使用它是不可能的(或至少是非平凡的)。但是,您可以在不进行任何排序的情况下完成,只需基于第一个元素收集索引:

from collections import defaultdict

lis = [[0, 1], [1, -1], [1, 0]]

d_idx = defaultdict(list)

for idx, item in enumerate(lis):
    d_idx[item[0]].append(idx)

然后创建一个“结果”列表,并反转具有相同第一个元素的所有元素的索引:

res = [None]*len(lis)

for _, value in d_idx.items():
    for orig_idx, target_idx in zip(value, reversed(value)):
        res[target_idx] = lis[orig_idx]

其中包含res

>>> res
[[0, 1], [1, 0], [1, -1]]

注意:使用相同的第一个元素“反转”元素可能不是理想的行为。因为@hiro protagonist noted in the comments

  

问题定义不明确...... lst = [(0,0), (0,1), (0,2)]:结果是什么?你在列表中迭代的次数和次数是多少?你什么时候做的?

如果您需要一个不同的行为,哪些元素应该分配到哪个位置,您(可能)只需要更改for orig_idx, target_idx in zip(value, reversed(value)):行并在那里应用您想要的操作。

另一个优点是此方法仅具有O(n)运行时行为,而sort具有O(n*log(n))(平均)运行时。所以它可能会更快。

答案 3 :(得分:0)

python排序方法将仅使用<对列表进行排序。项目之间的比较。你必须传递一个函数,它将每个元素映射到可以与其他映射元素进行比较的东西,以便小于'关系给出了期望的结果。

然而,您的规则并未定义任何类型的关系,可以用a < b来描述元素a,b。它只定义了相邻元素之间的关系,它甚至不是一个稳定的关系:如果a < b所以你交换这两个项,那么它立即成为b < a的情况。

或者简而言之,lis.sort()完全不适合此任务。