【问题标题】:Sorting Python dictionary by value; value is a two-item list; regular sort on first list item, reverse sort on second item按值对 Python 字典进行排序; value 是一个包含两项的列表;对第一个列表项进行常规排序,对第二项进行反向排序
【发布时间】:2020-11-11 10:50:52
【问题描述】:

我有一个字典,其值都是包含两项的列表(键是一个包含六项的元组,但我们不会深入探讨)。

这是一个可视化:

my_ridiculous_dict = {
    ('0', '2', '0', '4', '0', '1'): [1, 1000], 
    ('5', '3', '0', '2', '0', '0'): [1, 400], 
    ('3', '6', '0', '2', '0', '0'): [2, 3000], 
    ('4', '3', '0', '2', '0', '0'): [2, 80], 
    ('0', '0', '3', '9', '0', '3'): [3, 0]
}

我需要先按值列表中的第一项对其进行排序,然后对第二项进行反向排序。因此,您在上面看到的内容将被正确排序

抱歉,如果这个问题已经解决,但是我在按值排序字典时看到的所有问题似乎都假设一个简单的 int 或 str 作为值,并且我在使用 lambda 或考虑到这增加的复杂性,itemgetters。

应该提到我不介意分两次执行此操作,只是想 git'r'done!

非常感谢。

【问题讨论】:

  • 您不能真正对字典进行排序,请提供您期望的输出?
  • 问题已经解决了,谢谢

标签: python sorting dictionary


【解决方案1】:

字典不是用来排序的,但如果您将项目复制到列表中,您可以对列表进行排序。

mrd = {
('4', '3', '0', '2', '0', '0'): [2, 80], 
('0', '2', '0', '4', '0', '1'): [1, 1000], 
('3', '6', '0', '2', '0', '0'): [2, 3000], 
('5', '3', '0', '2', '0', '0'): [1, 400], 
('0', '0', '3', '9', '0', '3'): [3, 0]
}

lst = list(mrd)
lst.sort(key=lambda x:[mrd[x][0], -mrd[x][1]])
for i in lst: print(i, mrd[i])

输出:

('0', '2', '0', '4', '0', '1') [1, 1000]
('5', '3', '0', '2', '0', '0') [1, 400]
('3', '6', '0', '2', '0', '0') [2, 3000]
('4', '3', '0', '2', '0', '0') [2, 80]
('0', '0', '3', '9', '0', '3') [3, 0]

【讨论】:

    【解决方案2】:

    Python 使用稳定的排序

    更通用的解决方案依赖于 Python 中的排序是稳定的这一事实。这意味着如果两个项目的排序相同,那么它们将保持原来的顺序。

    要获得您想要的,请按第二个值进行反向排序。使用my_dict.items() 获取(键,值)元组。 t[1][1] 是第二个值。

    items = sorted(my_dict.items(), key=lambda t:t[1][1], reverse=True)
    

    然后按第一个值排序。

    items.sort(key=lambda t:t[1][0])
    

    在当前版本的 Python 中,dicts 以 key-insertion-order 维护项目。所以你可以通过以下方式创建一个排序的字典:

    my_sorted_dict = dict(items)
    

    使用 operator.itemgetter()

    我没有看到在嵌套数据结构上使用 itemgetter 的方法,例如 my_dict.items() 提供的 (key, [value1, value2])。因此,要使用operator.itemgetter(),结构需要被展平。

    import operator
    
    items = [(k, *v) for k,v in my_dict.items()]
    

    这会将它变成一个元组,例如:(k, value1, value2)。

    现在像以前一样对列表进行排序;第二个元素,然后是第一个元素。 operator.itemgetter(n) 创建并返回一个函数,该函数接受一个对象并在该对象上调用 __getitem__(n)。因此,这些行对 items 中的每个项目进行以 item[2] 为键的反向排序,然后以 item[1] 为键进行排序。

    items.sort(key=operator.itemgetter(2), reverse=True)
    items.sort(key=operator.itemgetter(1))
    

    然后一个字典推导构建排序的字典:

    my_sorted_dict = {k:[v1,v2] for k,v1,v2 in items}
    

    my_sorted_dict

    【讨论】:

    • 太棒了!我几乎走到了这一步,但由于据称具有性能优势,我专注于 itemgetters。
    • 如果有人知道如何通过 itemgetters 方法做到这一点,我很想听听
    • 在上面添加了 itemgetters()。
    猜你喜欢
    • 2017-02-17
    • 2022-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-02
    相关资源
    最近更新 更多