【问题标题】:Python3 asc desc sortingPython3 asc desc 排序
【发布时间】:2015-03-05 23:32:26
【问题描述】:

假设我有以下 python 列表(这只是示例):

my_list = [{'user': 'Joe', 'score': 14},
           {'user': 'Foo', 'score': 12},
           {'user': 'May', 'score': 12},
           {'user': 'Kat', 'score': 12},
           {'user': 'Doe', 'score': 13}]

我需要按分数升序和用户名降序对该列表进行排序。 预期排序结果:

my_list = [{'user': 'May', 'score': 12},
           {'user': 'Kat', 'score': 12},
           {'user': 'Foo', 'score': 12},
           {'user': 'Doe', 'score': 13},
           {'user': 'Joe', 'score': 14}]

所以,如果我希望所有内容都按升序排列,我可以这样做:

my_list.sort(key=lambda x: (x['score'], x['user']))

对于整数很容易解决这个问题,只需在它前面添加-

my_list.sort(key=lambda x: (-x['score'], x['user']))

不幸的是,字符串不能为负:-|

我需要一个不涉及“reverse=True”的通用解决方案。 Lambda 函数是根据用户配置动态生成的。

想法?

【问题讨论】:

标签: python list sorting python-3.x


【解决方案1】:

如果您将list.sortreverse 参数设置为True,您当前的解决方案将正常工作:

>>> my_list = [{'user': 'Joe', 'score': 14},
...            {'user': 'Foo', 'score': 12},
...            {'user': 'May', 'score': 12},
...            {'user': 'Kat', 'score': 12},
...            {'user': 'Doe', 'score': 13}]
>>> my_list.sort(key=lambda x: (-x['score'], x['user']), reverse=True)
>>> pprint(my_list) # pprint makes the nice output
[{'score': 12, 'user': 'May'},
 {'score': 12, 'user': 'Kat'},
 {'score': 12, 'user': 'Foo'},
 {'score': 13, 'user': 'Doe'},
 {'score': 14, 'user': 'Joe'}]
>>>

这将按相反的顺序对列表进行排序。


编辑:

由于名称和分数有两种不同的排序顺序,因此您需要使用两种不同的排序来实现所需的输出:

>>> my_list = [{'user': 'Joe', 'score': 14},
...            {'user': 'Foo', 'score': 12},
...            {'user': 'May', 'score': 12},
...            {'user': 'Kat', 'score': 12},
...            {'user': 'Doe', 'score': 13}]
>>> my_list.sort(key=lambda x: x['user'], reverse=True)
>>> my_list.sort(key=lambda x: x['score'])
>>> pprint(my_list)
[{'score': 12, 'user': 'May'},
 {'score': 12, 'user': 'Kat'},
 {'score': 12, 'user': 'Foo'},
 {'score': 13, 'user': 'Doe'},
 {'score': 14, 'user': 'Joe'}]
>>>

【讨论】:

  • 它仅适用于这种特殊情况,因为您可以使用整数值的符号。 reverse=True 会影响不可接受的整个列表顺序。我需要一些可以影响特定列的顺序的东西。就像在 SQL 中一样:ORDER by score ASC, USER desc, last_name ASC。
  • 查看我的编辑。在这种情况下,您需要使用两种排序(一种用于降序,另一种用于升序)。
【解决方案2】:

字符串的序号可以是负数:

my_list.sort(key=lambda x: (x["score"],[-ord(x) for x in x["user"]])))


In [50]:  my_list.sort(key=lambda x: (x["score"],[-ord(x) for x in x["user"]]))

In [51]: my_list
Out[51]: 
[{'score': 12, 'user': 'May'},
 {'score': 12, 'user': 'Kat'},
 {'score': 12, 'user': 'Foo'},
 {'score': 13, 'user': 'Doe'},
 {'score': 14, 'user': 'Joe'}]

【讨论】:

  • 哈哈!这绝对有效!但是,它非常慢:-|
  • @VladBenya,考虑到你不想使用反向,做你想做的事情很棘手,你可以在第一个字符上做 -ord(x["user"][0]) 作为妥协
【解决方案3】:

降序需要添加reverse=True关键字。

>>> my_list.sort(key=lambda x: (-x['score'], x['user']),reverse=True)
>>> my_list
[{'score': 12, 'user': 'May'}, {'score': 12, 'user': 'Kat'}, {'score': 12, 'user': 'Foo'}, {'score': 13, 'user': 'Doe'}, {'score': 14, 'user': 'Joe'}]

【讨论】:

  • 这只是针对此示例的自定义解决方案。我可能需要对三四个字段进行排序。它们中的每一个都可能在下降,也可能在上升。所有字段都可以是字符串。我正在寻找一个通用的解决方案。
  • @VladBenya 你是什么意思?当你使用reverse=Truesort函数时总是对可迭代的反向进行排序!
  • @VladBenya 所以为了这个目标你需要更新你的列表,不能只使用sort
  • 想象一下 score 是一个用户姓氏,它是一个字符串。我想按用户名升序排列这个列表,并将他们的姓氏降序排列。 reverse=True 在这里无济于事,因为它会影响整个列表的最终顺序。
猜你喜欢
  • 2017-10-27
  • 2014-07-11
  • 1970-01-01
  • 1970-01-01
  • 2018-05-26
  • 1970-01-01
  • 2021-08-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多