Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 将函数传递给排序函数的键_Python_List_Python 3.x_Sorting - Fatal编程技术网

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

Python 将函数传递给排序函数的键,python,list,python-3.x,sorting,Python,List,Python 3.x,Sorting,我有一张单子 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

我有一张单子

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]
我想将此函数传递给列表的排序方法,以便它根据以下逻辑进行排序:

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

lis.sort(key=sortList)

如何使此函数在排序方法中工作?

python排序方法将只使用<项之间的比较来对列表进行排序。您必须向它传递一个函数,该函数将每个元素映射到可以与其他映射元素进行比较的对象,以便“小于”关系给出所需的结果

然而,您的规则并没有定义任何类型的关系,这些关系可以用元素a、b的a
或者简而言之,lis.sort完全不适合此任务。

python排序方法将对列表进行排序,只使用<项之间的比较。您必须向它传递一个函数,该函数将每个元素映射到可以与其他映射元素进行比较的对象,以便“小于”关系给出所需的结果

然而,您的规则并没有定义任何类型的关系,这些关系可以用元素a、b的a
或者简言之,lis.sort完全不适合此任务。

您无法使它可靠地与list.sort或sorted一起工作。问题在于,这些函数背后的排序算法不能保证比较了哪些元素,而只是说结果会被排序。要使list.sort或sorted可靠地工作,您需要一个键的名称,而您的函数不提供该名称


此外,键应该是一个将一个元素转换为应比较属性的函数,它确实会将列表中的每个元素传递给键函数,而不是CPyth中的总列表。在排序时,该列表为空,因此它根本无法工作。

使用list.sort或sorted无法使其可靠工作。问题在于,这些函数背后的排序算法不能保证比较了哪些元素,而只是说结果会被排序。要使list.sort或sorted可靠地工作,您需要一个键的名称,而您的函数不提供该名称


此外,键应该是一个函数,它将一个元素转换为应该比较的属性,它会将列表中的每个元素传递给键函数,而不是CPython中的总列表,因为排序时列表为空,因此它根本无法工作。

执行此排序的一种方法是使用cmp参数对Python 3进行排序,并在两个子列表的索引0处的项比较相等或为零时返回-1。这假设项目是成对的,并且是连续的,因此这并不是一种真正的穷举排序,只是一种交换项目的黑客方式:

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,您可以在列表中循环并交换符合您条件的成对连续项。无需应用排序

执行此排序的一种方法是在Python 3中使用cmp参数进行排序,并在两个子列表的索引0处的项比较相等或为零时返回-1。这假设项目是成对的,并且是连续的,因此这并不是一种真正的穷举排序,只是一种交换项目的黑客方式:

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,您可以在列表中循环并交换符合您条件的成对连续项。无需应用排序

正如在其他答案中已经说过的那样,要让它与排序一起工作是不可能的,或者至少是非常重要的。但是,您可以不进行任何排序,只需根据第一个元素收集索引:

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]
然后创建一个结果列表,只需反转具有相同第一个元素的所有元素的索引:

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]
其中给出了以下结果:

注意:使用相同的第一个元素反转元素可能不是所需的行为。因为:


这个问题并不是很明确。。。lst=[0,0,0,1,0,2]:结果是什么?您在列表上迭代了多少次?你什么时候做完

万一你 你需要一个不同的行为,哪些元素应该被分配到哪个位置,你可能只需要更改zipvalue,reversedvalue:line中的for orig_idx,target_idx,并在那里应用你想要的操作


另一个优点是,这种方法只具有On运行时行为,而sort具有On*logn平均运行时行为。因此,它可以更快。

正如在其他答案中已经说过的那样,让它与排序一起工作是不可能的,或者至少是非常重要的。但是,您可以不进行任何排序,只需根据第一个元素收集索引:

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]
然后创建一个结果列表,只需反转具有相同第一个元素的所有元素的索引:

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]
其中给出了以下结果:

注意:使用相同的第一个元素反转元素可能不是所需的行为。因为:


这个问题并不是很明确。。。lst=[0,0,0,1,0,2]:结果是什么?您在列表上迭代了多少次?你什么时候做完

如果您需要不同的行为,哪些元素应该分配到哪个位置,您可能只需要更改zipvalue中的for orig_idx、target_idx、reversedvalue:行并在那里应用所需的操作


另一个优点是,这种方法只具有On运行时行为,而sort具有On*logn平均运行时行为。所以它可以更快。

这与排序不同。。。排序必须是全局属性,而不是直接依赖于邻居。合并排序如何工作?还是其他排序算法?结果如何相同?]@男主角,那么我还有别的办法吗?问题并不是很明确。。。lst=[0,0,0,1,0,2]:结果是什么?您在列表上迭代了多少次?你什么时候做的?这和分类不一样。。。排序必须是全局属性,而不是直接依赖于邻居。合并排序如何工作?还是其他排序算法?结果如何相同?]@男主角,那么我还有别的办法吗?问题并不是很明确。。。lst=[0,0,0,1,0,2]:结果是什么?您在列表上迭代了多少次?什么时候完成?而且不能保证所有项目都会相互比较。因此,它可能会起作用,也可能不起作用,这取决于比较的项目。@Moses您能在python 3中显示相同的实现吗?我尝试使用functools.cmp_to_键,但出现了错误。@SouvikRay sortedlis,key=functools.cmp_to_keylambda x,y:-1如果x[0]==y[0]其他的0@SouvikRay请记住导入functools并查看其他答案。并且不能保证所有项目都会相互比较。因此,它可能会起作用,也可能不起作用,这取决于比较的项目。@Moses您能在python 3中显示相同的实现吗?我尝试使用functools.cmp_to_键,但出现了错误。@SouvikRay sortedlis,key=functools.cmp_to_keylambda x,y:-1如果x[0]==y[0]其他0@SouvikRay请记住导入functools并查看其他答案。酷!所以我最好不要使用排序功能,试着用你的方式:酷!因此,我最好不要使用排序功能,而是尝试按您的方式进行排序: