Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.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_Sorting - Fatal编程技术网

按两个字段对Python列表进行排序

按两个字段对Python列表进行排序,python,sorting,Python,Sorting,我已经从排序的csv创建了以下列表 list1 = sorted(csv1, key=operator.itemgetter(1)) 实际上,我想按照两个标准对列表进行排序:首先是字段1中的值,然后是字段2中的值。我该怎么做?像这样: import operator list1 = sorted(csv1, key=operator.itemgetter(1, 2)) sort_array(list1, 2, 1) Python有一个稳定的排序,所以只要性能不是问题,最简单的方法就是按字段

我已经从排序的csv创建了以下列表

list1 = sorted(csv1, key=operator.itemgetter(1))
实际上,我想按照两个标准对列表进行排序:首先是字段1中的值,然后是字段2中的值。我该怎么做?

像这样:

import operator
list1 = sorted(csv1, key=operator.itemgetter(1, 2))
sort_array(list1, 2, 1)

Python有一个稳定的排序,所以只要性能不是问题,最简单的方法就是按字段2排序,然后再按字段1排序

这将为您提供您想要的结果,唯一的问题是,如果它是一个大列表(或者您想经常对它进行排序),那么调用sort两次可能是不可接受的开销

list1 = sorted(csv1, key=operator.itemgetter(2))
list1 = sorted(list1, key=operator.itemgetter(1))
这样做还可以方便地处理某些列需要反向排序的情况,必要时只需包含“reverse=True”参数

否则,您可以将多个参数传递给itemgetter或手动构建元组。这可能会更快,但存在一个问题,即如果某些列希望进行反向排序(数值列仍然可以通过对其求反来进行反向排序,但这会停止排序的稳定),则不能很好地进行推广

因此,如果您不需要对任何列进行反向排序,那么可以选择itemgetter的多个参数,如果可能的话,并且这些列不是数字列,或者您希望保持排序稳定,可以选择多个连续排序

编辑:对于理解这如何回答原始问题有困难的评论者,下面的示例准确地说明了排序的稳定性如何确保我们可以对每个键进行单独排序,并最终根据多个条件对数据进行排序:

DATA = [
    ('Jones', 'Jane', 58),
    ('Smith', 'Anne', 30),
    ('Jones', 'Fred', 30),
    ('Smith', 'John', 60),
    ('Smith', 'Fred', 30),
    ('Jones', 'Anne', 30),
    ('Smith', 'Jane', 58),
    ('Smith', 'Twin2', 3),
    ('Jones', 'John', 60),
    ('Smith', 'Twin1', 3),
    ('Jones', 'Twin1', 3),
    ('Jones', 'Twin2', 3)
]

# Sort by Surname, Age DESCENDING, Firstname
print("Initial data in random order")
for d in DATA:
    print("{:10s} {:10s} {}".format(*d))

print('''
First we sort by first name, after this pass all
Twin1 come before Twin2 and Anne comes before Fred''')
DATA.sort(key=lambda row: row[1])

for d in DATA:
    print("{:10s} {:10s} {}".format(*d))

print('''
Second pass: sort by age in descending order.
Note that after this pass rows are sorted by age but
Twin1/Twin2 and Anne/Fred pairs are still in correct
firstname order.''')
DATA.sort(key=lambda row: row[2], reverse=True)
for d in DATA:
    print("{:10s} {:10s} {}".format(*d))

print('''
Final pass sorts the Jones from the Smiths.
Within each family members are sorted by age but equal
age members are sorted by first name.
''')
DATA.sort(key=lambda row: row[0])
for d in DATA:
    print("{:10s} {:10s} {}".format(*d))
这是一个可运行的示例,但为了节省运行它的人员,输出为:

Initial data in random order
Jones      Jane       58
Smith      Anne       30
Jones      Fred       30
Smith      John       60
Smith      Fred       30
Jones      Anne       30
Smith      Jane       58
Smith      Twin2      3
Jones      John       60
Smith      Twin1      3
Jones      Twin1      3
Jones      Twin2      3

First we sort by first name, after this pass all
Twin1 come before Twin2 and Anne comes before Fred
Smith      Anne       30
Jones      Anne       30
Jones      Fred       30
Smith      Fred       30
Jones      Jane       58
Smith      Jane       58
Smith      John       60
Jones      John       60
Smith      Twin1      3
Jones      Twin1      3
Smith      Twin2      3
Jones      Twin2      3

Second pass: sort by age in descending order.
Note that after this pass rows are sorted by age but
Twin1/Twin2 and Anne/Fred pairs are still in correct
firstname order.
Smith      John       60
Jones      John       60
Jones      Jane       58
Smith      Jane       58
Smith      Anne       30
Jones      Anne       30
Jones      Fred       30
Smith      Fred       30
Smith      Twin1      3
Jones      Twin1      3
Smith      Twin2      3
Jones      Twin2      3

Final pass sorts the Jones from the Smiths.
Within each family members are sorted by age but equal
age members are sorted by first name.

Jones      John       60
Jones      Jane       58
Jones      Anne       30
Jones      Fred       30
Jones      Twin1      3
Jones      Twin2      3
Smith      John       60
Smith      Jane       58
Smith      Anne       30
Smith      Fred       30
Smith      Twin1      3
Smith      Twin2      3

请特别注意,在第二步中,
reverse=True
参数如何保持名字的顺序,而简单地排序然后反转列表将丢失第三个排序键所需的顺序。

使用lambda函数时无需导入任何内容。
以下内容按第一个元素排序,然后按第二个元素排序

sorted_list=sorted(list,key=lambda x:(x[0],-x[1]))
我们还可以将.sort与lambda一起使用2次,因为python排序已经就位且稳定。这将首先根据第二个元素x[1]对列表进行排序。然后,它将对第一个元素x[0](最高优先级)进行排序

这相当于执行以下操作:
排序(key=lambda x:(x[0],x[1])

下面使用的DICT排序列表将按降序在第一列中排序为工资,在第二列中排序为年龄

d=[{'salary':123,'age':23},{'salary':123,'age':25}]
d=sorted(d, key=lambda i: (i['salary'], i['age']),reverse=True)

输出:[{'salary':123,'age':25},{'salary':123,'age':23}]

按升序可以使用:

sorted_data= sorted(non_sorted_data, key=lambda k: (k[1],k[0]))
sorted_data= sorted(non_sorted_data, key=lambda k: (k[1],k[0]),reverse=True)
或按降序使用:

sorted_data= sorted(non_sorted_data, key=lambda k: (k[1],k[0]))
sorted_data= sorted(non_sorted_data, key=lambda k: (k[1],k[0]),reverse=True)
python 3


在阅读了本帖中的答案后,我编写了一个通用解决方案,可用于任意数量的列:

def sort_array(array, *columns):
    for col in columns:
        array.sort(key = lambda x:x[col])
OP会这样称呼它:

import operator
list1 = sorted(csv1, key=operator.itemgetter(1, 2))
sort_array(list1, 2, 1)
首先按第2列排序,然后按第1列排序。

(最重要的栏目排在最后)

+1:比我的更优雅。我忘了itemgetter可以获取多个索引。
运算符
是一个需要导入的模块。如果我想使用itemgetter对一个元素进行升序排序,并对另一个元素进行降序排序,我将如何进行操作???@ashish,请参阅我下面关于lambda函数的答案。这很清楚,按“-x[1]”甚至“x[0]+x[1]”排序如果你想知道是否有一个条件处于反向模式?稳定的排序并不意味着它不会忘记你以前的排序是什么。这个答案是错误的。稳定排序意味着您可以按a、b、c列排序,只需按c列、b列和a列排序即可。除非你想对你的评论进行扩展,否则我认为是你错了。这个答案肯定是正确的,尽管对于更大的列表来说,这是不可能的:如果列表已经部分排序,那么你将失去Python排序的大部分优化,因为你会对列表进行更多的乱序@迈克,你错了;我建议在宣布答案错误之前先测试答案。@MikeAxiak:在注释9中指出:从Python 2.3开始,sort()方法保证是稳定的。如果排序保证不改变比较相等的元素的相对顺序,则排序是稳定的-这有助于在多个过程中进行排序(例如,按部门排序,然后按薪资等级排序)。这是不正确的,因为这没有回答他提出的问题。他想要一个按第一个索引排序的列表,如果第一个索引中有关系,他想要使用第二个索引作为排序标准。一个稳定的排序只能保证所有东西都是相等的,传递的原始顺序将是项目出现的顺序。我不认为
tuple()
可以接收两个参数(或者更确切地说,如果使用
self
计数,则可以接收三个)。tuple take只能接收一个参数
return
语句应该是
return tuple((x[1],x[2])
或简单地
返回x[1],x[2]
@如果您正在寻找不同方向的排序…或
tuple(x[1:3])
,如果您出于某种原因想使用tuple构造函数,而不仅仅是一个tuple显示列表
x[1],x[2]
,请回答下面的jaap。或者
keyfunc=operator.itemgetter(1,2)
,甚至不自己编写函数。很好。正如您在对上述主要答案的评论中所指出的,这是使用不同排序顺序进行多个排序的最佳(唯一?)方法。也许可以强调这一点。另外,您的文本并不表示您按第二个元素降序排序。@user1700890我假设该字段已经是字符串。默认情况下,它应该按字母顺序对字符串进行排序。如果你的问题与这里的答案或OP的原始问题没有特别的关系,你应该单独在上面张贴你自己的问题。
-x[1]
中的
-
代表什么?@jan它是相反的,在一个特定的情况下不起作用。被接受的解决方案也不会起作用。例如,用作键的列都是无法转换为数字的字符串。其次