【问题标题】:Sort nested dictionary by value, and remainder by another value, in Python在Python中按值对嵌套字典进行排序,并按另一个值对余数进行排序
【发布时间】:2011-05-05 20:53:19
【问题描述】:

考虑这种字典格式。

{'KEY1':{'name':'google','date':20100701,'downloads':0},
 'KEY2':{'name':'chrome','date':20071010,'downloads':0},
 'KEY3':{'name':'python','date':20100710,'downloads':100}}

我希望字典首先按下载次数排序,然后所有没有下载的项目按日期排序。显然字典无法排序,我只需要一个可以迭代的键的排序列表。

['KEY3','KEY1','KEY2']

我已经可以使用sorted 按任一值对列表进行排序,但如何也按第二个值排序?

【问题讨论】:

    标签: python sorting dictionary python-2.5


    【解决方案1】:

    sorted() 使用key 参数。它允许您指定一个函数,在给定实际排序的项目的情况下,返回一个应该排序的值。如果这个值是一个元组,那么它的排序就像元组排序一样 - 按第一个值,然后按第二个值。

    sorted(your_list, key=lambda x: (your_dict[x]['downloads'], your_dict[x]['date']))
    

    【讨论】:

    • 非常好的线路!以下是颠倒排序顺序的方法:只需将reverse=True 作为参数添加到sorted 函数的末尾即可。谢谢
    • 改成上面那个。 your_list = sorted(your_dict, key=lambda x: (your_dict[x]['downloads'], your_dict[x]['date']))
    • 嗨,我在调用 sorted(d.items(), key=lambda x: (d[x]['downloads'], d[x]['date'])) 时收到错误 TypeError: unhashable type: 'dict',其中 d 等于 OP 中的字典。如果有人知道问题,请告诉我。谢谢
    • @ChickenFeet 使用 d.keys() 而不是 d.items()
    • 这只是返回键,有没有办法获取键和您排序的项目?例如,有没有办法做到sorted((d.keys(), lambda y: d[y]['downloads']), key=lambda x: (d[x]['downloads']) 实际上是正确的?该代码原样向我抛出相同的 TypeError @ChickenFeet 得到
    【解决方案2】:

    您可以将key 函数传递给sorted,它会返回一个包含您希望排序的两件事的元组。假设你的大字典叫d

    def keyfunc(tup):
        key, d = tup
        return d["downloads"], d["date"]
    
    items = sorted(d.items(), key = keyfunc)
    

    如果您愿意,可以使用lambda 执行此操作,但这可能更清楚。下面是等效的基于 lambda 的代码:

    items = sorted(d.items(), key = lambda tup: (tup[1]["downloads"], tup[1]["date"]))
    

    顺便说一句,由于您提到要先按“下载”排序,所以上述两个示例按下载次数升序排序。但是,从上下文来看,您可能希望按下载的降序排序,在这种情况下您会说

    return -d["downloads"], d["date"]
    

    在您的keyfunc 中。如果您想要按升序对非零下载数进行排序,然后在此之后拥有所有零下载记录,您可以这样说

    return (-d["downloads"] or sys.maxint), d["date"]
    

    【讨论】:

    • 我都试过了,但是我得到的不是一个键列表,而是一个元组列表。我也可以使用它,但它是不必要的复杂性。 [('KEY3',{'name':'python','date':20100710,'downloads':100})]
    • @user479870 您可以使用[x[0] for x in items] 从元组中获取密钥。
    【解决方案3】:

    我的另一个答案是错误的(这里的大多数答案都是错误的)

    sorted_keys = sorted((key for key in outer_dict if outer_dict[key]['downloads']),
                         key=lambda x: (outer_dict[key]['downloads'],
                                        outer_dict[key]['downloads'])
                         reverse=True)
    
    sorted_keys += sorted((key for key in outer_dict if not outer_dict[key]['downloads']),
                          key=lambda x: outer_dict[key]['date'])
    

    这将创建一个列表,其中已下载的项目按降序排列在其前面,其余未下载的项目按日期排序在已下载的项目之后。

    但实际上,Eli Courtwrights answer 的最后一部分是最好的。

    【讨论】:

    • 呃,你为什么import-ing operator 然后从不使用它?
    • @Amber 因为我以为我要做点别的事情,然后开始下雨了。我很着急。现在在里面。
    • 未经测试。为什么在第一个 lambda x: 之后有两个 outer_dict[key]['downloads'] 的元组?
    【解决方案4】:
    your_dict = dict(sorted(your_dict.items(), key = lambda x: (x[1]["downloads"], x[1]["date"])))
    

    【讨论】:

    • 虽然这个答案可能会回答这个问题,但如果您稍微解释一下代码会很好,例如为什么它是这样构建的,它是如何工作的等等。
    【解决方案5】:
    a = {'KEY1':{'name':'google','date':20100701,'downloads':0},
     'KEY2':{'name':'chrome','date':20071010,'downloads':0},
     'KEY3':{'name':'python','date':20100710,'downloads':100}}
    
    
    z = a.items()
    
    z.sort(key=lambda x: (x[1]['downloads'], x[1]['date']))
    

    【讨论】:

    • z.sort(key=lambda x: (x[1]['downloads'], x[1]['date'])) 返回无。知道为什么吗?
    猜你喜欢
    • 1970-01-01
    • 2014-05-01
    • 1970-01-01
    • 2021-03-08
    • 2020-11-11
    • 1970-01-01
    • 2019-09-09
    • 1970-01-01
    • 2018-11-23
    相关资源
    最近更新 更多