当前位置: 首页 > 面试题库 >

如何在Python中按多个键对对象排序?

长孙诚
2023-03-14
问题内容

或者,实际上,如何按多个键对词典列表进行排序?

我有一个字典列表:

b = [{u'TOT_PTS_Misc': u'Utley, Alex', u'Total_Points': 96.0},
 {u'TOT_PTS_Misc': u'Russo, Brandon', u'Total_Points': 96.0},
 {u'TOT_PTS_Misc': u'Chappell, Justin', u'Total_Points': 96.0},
 {u'TOT_PTS_Misc': u'Foster, Toney', u'Total_Points': 80.0},
 {u'TOT_PTS_Misc': u'Lawson, Roman', u'Total_Points': 80.0},
 {u'TOT_PTS_Misc': u'Lempke, Sam', u'Total_Points': 80.0},
 {u'TOT_PTS_Misc': u'Gnezda, Alex', u'Total_Points': 78.0},
 {u'TOT_PTS_Misc': u'Kirks, Damien', u'Total_Points': 78.0},
 {u'TOT_PTS_Misc': u'Worden, Tom', u'Total_Points': 78.0},
 {u'TOT_PTS_Misc': u'Korecz, Mike', u'Total_Points': 78.0},
 {u'TOT_PTS_Misc': u'Swartz, Brian', u'Total_Points': 66.0},
 {u'TOT_PTS_Misc': u'Burgess, Randy', u'Total_Points': 66.0},
 {u'TOT_PTS_Misc': u'Smugala, Ryan', u'Total_Points': 66.0},
 {u'TOT_PTS_Misc': u'Harmon, Gary', u'Total_Points': 66.0},
 {u'TOT_PTS_Misc': u'Blasinsky, Scott', u'Total_Points': 60.0},
 {u'TOT_PTS_Misc': u'Carter III, Laymon', u'Total_Points': 60.0},
 {u'TOT_PTS_Misc': u'Coleman, Johnathan', u'Total_Points': 60.0},
 {u'TOT_PTS_Misc': u'Venditti, Nick', u'Total_Points': 60.0},
 {u'TOT_PTS_Misc': u'Blackwell, Devon', u'Total_Points': 60.0},
 {u'TOT_PTS_Misc': u'Kovach, Alex', u'Total_Points': 60.0},
 {u'TOT_PTS_Misc': u'Bolden, Antonio', u'Total_Points': 60.0},
 {u'TOT_PTS_Misc': u'Smith, Ryan', u'Total_Points': 60.0}]

并且我需要使用由Total_Points反转的多键排序,然后不由反转TOT_PTS_Misc

可以在命令提示符下完成,如下所示:

a = sorted(b, key=lambda d: (-d['Total_Points'], d['TOT_PTS_Misc']))

但是我必须通过一个函数来运行它,在其中传递列表和排序键。例如,def multikeysort(dict_list, sortkeys):

对于传递给multikeysort函数的任意数量的键,如何使用lambda行将对列表进行排序,并考虑到sortkey可以具有任意数量的键,并且需要识别需要反向排序的键前面加上“-”?


问题答案:

此答案适用于字典中的任何列-否定的列不必是数字。

def multikeysort(items, columns):
    from operator import itemgetter
    comparers = [((itemgetter(col[1:].strip()), -1) if col.startswith('-') else
                  (itemgetter(col.strip()), 1)) for col in columns]
    def comparer(left, right):
        for fn, mult in comparers:
            result = cmp(fn(left), fn(right))
            if result:
                return mult * result
        else:
            return 0
    return sorted(items, cmp=comparer)

您可以这样称呼它:

b = [{u'TOT_PTS_Misc': u'Utley, Alex', u'Total_Points': 96.0},
     {u'TOT_PTS_Misc': u'Russo, Brandon', u'Total_Points': 96.0},
     {u'TOT_PTS_Misc': u'Chappell, Justin', u'Total_Points': 96.0},
     {u'TOT_PTS_Misc': u'Foster, Toney', u'Total_Points': 80.0},
     {u'TOT_PTS_Misc': u'Lawson, Roman', u'Total_Points': 80.0},
     {u'TOT_PTS_Misc': u'Lempke, Sam', u'Total_Points': 80.0},
     {u'TOT_PTS_Misc': u'Gnezda, Alex', u'Total_Points': 78.0},
     {u'TOT_PTS_Misc': u'Kirks, Damien', u'Total_Points': 78.0},
     {u'TOT_PTS_Misc': u'Worden, Tom', u'Total_Points': 78.0},
     {u'TOT_PTS_Misc': u'Korecz, Mike', u'Total_Points': 78.0},
     {u'TOT_PTS_Misc': u'Swartz, Brian', u'Total_Points': 66.0},
     {u'TOT_PTS_Misc': u'Burgess, Randy', u'Total_Points': 66.0},
     {u'TOT_PTS_Misc': u'Smugala, Ryan', u'Total_Points': 66.0},
     {u'TOT_PTS_Misc': u'Harmon, Gary', u'Total_Points': 66.0},
     {u'TOT_PTS_Misc': u'Blasinsky, Scott', u'Total_Points': 60.0},
     {u'TOT_PTS_Misc': u'Carter III, Laymon', u'Total_Points': 60.0},
     {u'TOT_PTS_Misc': u'Coleman, Johnathan', u'Total_Points': 60.0},
     {u'TOT_PTS_Misc': u'Venditti, Nick', u'Total_Points': 60.0},
     {u'TOT_PTS_Misc': u'Blackwell, Devon', u'Total_Points': 60.0},
     {u'TOT_PTS_Misc': u'Kovach, Alex', u'Total_Points': 60.0},
     {u'TOT_PTS_Misc': u'Bolden, Antonio', u'Total_Points': 60.0},
     {u'TOT_PTS_Misc': u'Smith, Ryan', u'Total_Points': 60.0}]

a = multikeysort(b, ['-Total_Points', 'TOT_PTS_Misc'])
for item in a:
    print item

尝试对任一列取反。您将看到排序顺序相反。

下一步:对其进行更改,以使其不使用额外的类。

2016-01-17

从这个答案中汲取灵感,从满足条件的可迭代项中获取第一项的最佳方法是什么?,我缩短了代码:

from operator import itemgetter as i

def multikeysort(items, columns):
    comparers = [
        ((i(col[1:].strip()), -1) if col.startswith('-') else (i(col.strip()), 1))
        for col in columns
    ]
    def comparer(left, right):
        comparer_iter = (
            cmp(fn(left), fn(right)) * mult
            for fn, mult in comparers
        )
        return next((result for result in comparer_iter if result), 0)
    return sorted(items, cmp=comparer)

如果您喜欢简洁的代码。

2016年1月17日晚

这适用于python3(消除了的cmp参数sort):

from operator import itemgetter as i
from functools import cmp_to_key

def cmp(x, y):
    """
    Replacement for built-in function cmp that was removed in Python 3

    Compare the two objects x and y and return an integer according to
    the outcome. The return value is negative if x < y, zero if x == y
    and strictly positive if x > y.

    https://portingguide.readthedocs.io/en/latest/comparisons.html#the-cmp-function
    """

    return (x > y) - (x < y)

def multikeysort(items, columns):
    comparers = [
        ((i(col[1:].strip()), -1) if col.startswith('-') else (i(col.strip()), 1))
        for col in columns
    ]
    def comparer(left, right):
        comparer_iter = (
            cmp(fn(left), fn(right)) * mult
            for fn, mult in comparers
        )
        return next((result for result in comparer_iter if result), 0)
    return sorted(items, key=cmp_to_key(comparer))

受此答案启发,如何在Python 3中自定义排序?



 类似资料:
  • 问题内容: 这将是一个很好的方式,从去到 我检查了一些帖子,但它们都使用了返回元组的”sorted” 运算符。 问题答案: 标准Python字典是无序的。即使你对(key,value)对进行了排序,也无法以保留顺序的方式存储它们。 最简单的方法是使用OrderedDict,它可以记住元素插入的顺序: 没关系od打印方式;它会按预期工作: Python 3 对于Python 3用户,需要使用.ite

  • 问题内容: 从这个原始问题开始,我将如何对多个字段进行排序? 使用这种略微适应的结构,我该如何对城市(升序)和价格(降序)进行排序? 我喜欢这个事实,而不是给出一个提供通用方法的答案。在计划使用此代码的地方,我将必须对日期以及其他内容进行排序。“灌注”物体的功能似乎很方便,即使有点麻烦。 我试图将这个答案构建成一个很好的通用示例,但是我运气不高。 问题答案: 这是一个“优化”版本。它进行了更多的预

  • 问题内容: 我有一个同时包含键和值的字符串的Map。 数据如下: 我想根据其键对地图进行排序。因此,最后,我将拥有..依此类推。 最终,我试图从该Map中获取两个字符串。 第一个字符串:问题(顺序为1 ..10) 第二个字符串:答案(与问题的顺序相同) 现在,我有以下内容: 这使我的问题成串出现,但顺序不正确。 问题答案: 简短答案 使用。这正是它的目的。 如果将此地图传递给你,并且你无法确定类型

  • 问题内容: 这应该很简单,但是要怎么做呢。我想通过一个键对多维数组进行排序,如下所示: 说我想按[状态]排序,我将如何实现呢?提前致谢! 问题答案: 那应该做您想要的,您可以更改比较功能以对想要的任何键进行排序。

  • 问题内容: 我有一个Java对象列表,希望根据多个字段进行排序。 是否可以使用或接口根据多个字段对列表进行排序?我看到的所有示例仅根据一个领域进行排序。换句话说,可以按“校园”或“教师”或“建筑”进行排序。我想按“校园”,“教师”,“建筑”(因为它在SQL中存在)进行排序 问题答案: 您的比较器如下所示: 基本上,只要到目前为止已比较的属性相等(),它就会继续比较类的每个连续属性。

  • 问题内容: 我需要通过PHP脚本中的“得分”值对此类信息进行排序,该怎么办?: PS:这已经在PHP值中,我已经使用了json_decode。* 问题答案: 当这个样子的: 您可以用来对数组进行排序: 输出: