按字典值排序对象的字典列表

时间:2009-07-29 18:17:25

标签: python django

这与我在这里读到的关于排序词典值的各种其他问题有关,但我没有找到答案。我是新手,也许我只是没有看到答案,因为它关系到我的问题。

我有这个函数,我用它作为Django自定义过滤器来排序字典列表中的结果。实际上,这个函数的主要部分是在stackoverflow的相关问题中回答的。

def multikeysorting(dict_list, sortkeys):
    from operator import itemgetter

    def multikeysort(items, columns):
        comparers = [ ((itemgetter(col[1:]), -1) if col.startswith('-') else (itemgetter(col), 1)) for col in columns]

        def sign(a, b):
            if a < b:   return -1
            elif a > b: return 1
            else:       return 0

        def comparer(left,right):
            for fn, mult in comparers:
                result = sign(fn(left), fn(right))
                if result:
                    return mult * result
            else:
                return 0

        return sorted(items, cmp=comparer)

    keys_list = sortkeys.split(",")
    return multikeysort(dict_list, keys_list)

在Django中调用此过滤器如下:

{% for item in stats|statleaders_has_stat:"TOT_PTS_Misc"|multikeysorting:"-TOT_PTS_Misc.value,TOT_PTS_Misc.player.last_name" %}

这意味着有两个字典值传递给函数以对字典列表进行排序。排序适用于字典键,但不适用于值。

如何通过对具有多个值的字典列表进行排序来对字典进行排序和返回?在上面的示例中,首先是值,然后是last_name。

以下是数据示例:     

[{u'TOT_PTS_Misc': < StatisticPlayerRollup: DeWitt, Ash Total Points : 6.0>, 'player': < Player: DeWitt, Ash>}, 
{u'TOT_PTS_Misc': < StatisticPlayerRollup: Ackerman, Luke Total Points : 18.0>, 'player': < Player: Ackerman, Luke>}, 
{u'TOT_PTS_Misc': < StatisticPlayerRollup: Wise, Dan Total Points : 19.0>, 'player': < Player: Wise, Dan>}, 
{u'TOT_PTS_Misc': < StatisticPlayerRollup: Allison, Mike Total Points : 18.0>, 'player': < Player: Allison, Mike>}, 
{u'TOT_PTS_Misc': < StatisticPlayerRollup: Wolford, Alex Total Points : 18.0>, 'player': < Player: Wolford, Alex>}, 
{u'TOT_PTS_Misc': < StatisticPlayerRollup: Okes, Joe Total Points : 18.0>, 'player': < Player: Okes, Joe>}, 
{u'TOT_PTS_Misc': < StatisticPlayerRollup: Grattan, Paul Total Points : 18.0>, 'player': < Player: Grattan, Paul>}]
    

列表应按如下方式排序:

LastName Points
Wise 19.0
Ackerman 18.0
Allison 18.0
Grattan 18.0
Okes 18.0
Wolford 18.0
Hagg 6.0
DeWitt 6.0

TOT_PTS_Misc是一个包含玩家名称和点数的对象。 (我希望我解释这是正确的。)

但是,应该有一个任意类型的值,无论是升序还是降序。并不总是相同的值,可能超过两个。


所以我提出了这个解决方案,但想知道它是否有意义以及是否有任何应该改变的内容。

def multikeysorting(dict_list, sortkeys):
    from operator import itemgetter, attrgetter

    klist = sortkeys.split(",")
    vlist = []
    for i in klist:
        vlist.append(tuple(i.split(".")))

    def getkeyvalue(val_list):
        result = []
        for id,val in enumerate(val_list):
            if val[0].startswith('-'):
                if len(val) == 2:
                    result.append((itemgetter(val[0][1:]).attrgetter(val[1]), -1))
                else:
                    att = val[1]
                    for j in val[2:]:
                        att = att + "." + j
                    result.append((itemgetter(val[0][1:]).attrgetter(att), -1))
            else:
                if len(val) == 2:
                    result.append((itemgetter(val[0]).attrgetter(val[1]), 1))
                else:
                    att = val[1]
                    for j in val[2:]:
                        att = att + "." + j
                    result.append((itemgetter(val[0]).attrgetter(att), 1))
        return result

    return sorted(dict_list, key=getkeyvalue(vlist))

2 个答案:

答案 0 :(得分:2)

您可以使用itemgetter访问密钥,使用attrgetter访问值属性。

因此,一旦您提取了您感兴趣的密钥,值名称,就可以构建您的密钥功能:

from operator import attrgetter, itemgetter
itmget = itemgetter('TOT_PTS_Misc')
attget_v = attrgetter('value')
attget_l = attrgetter('last_name')
def keyfunc(x):
    itm = itmget(x)
    return (-attget_v(itm), attget_n(itm))
sorted(dictlist, key=keyfunc)

这似乎有效。这是你问的问题吗?或者我错过了什么?

答案 1 :(得分:0)

据我所知,您需要做两件事。

首先,从排序键解析调用路径,即:将'TOT_PTS_Misc.value'转为('TOT_PTS_Misc','value') 其次,使用attrgetter以类似于itemgetter的使用方式,用于可调用部分。

如果我没弄错的话,itemgetter('TOT_PTS_Misc').attrgetter('value')应该等于dict['TOT_PTS_Misc'].value