简体   繁体   English

按值对 Python 字典进行排序; value 是一个包含两项的列表; 对第一个列表项进行常规排序,对第二项进行反向排序

[英]Sorting Python dictionary by value; value is a two-item list; regular sort on first list item, reverse sort on second item

I have a dictionary whose values are all two-item lists (the key is a six-item tuple, but we won't get into that).我有一个字典,它的值都是两项列表(关键是一个六项元组,但我们不会进入那个)。

Here's a visualization:这是一个可视化:

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]
}

I need to sort it first by the first item in the value's list, then with a reverse sort on the second item.我需要先按值列表中的第一项对其进行排序,然后对第二项进行反向排序。 So what you see above would be sorted correctly因此,您在上面看到的内容将被正确排序

Apologies if this has been addressed, but all the questions I've seen on sorting dictionaries by value seem to assume a simple int or str as the value, & I'm having trouble wrapping my head around the use of lambdas or itemgetters given this added complexity.抱歉,如果已解决此问题,但是我在按值排序字典时看到的所有问题似乎都假定一个简单的 int 或 str 作为值,并且鉴于此,我很难理解 lambda 或 itemgetters 的使用增加了复杂性。

Should mention I don't mind doing this in two sort passes, just would like to git'r'done!应该提到我不介意分两次这样做,只是想完成!

Many thanks in advance.提前谢谢了。

Dictionaries aren't meant to be sorted but if you copy the items to a list, you can sort the list.字典不是要排序的,但如果将项目复制到列表中,则可以对列表进行排序。

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])

Output: Output:

('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]

Python uses a stable sort Python 使用稳定排序

A more general solution relies on the fact that the sorts are stable in Python.更通用的解决方案依赖于 Python 中的排序是稳定的这一事实。 That means that if two items sort the same, then they retain their original order.这意味着如果两个项目排序相同,那么它们将保留其原始顺序。

To get what you want, do a reversed sort by the second value.要获得您想要的,请按第二个值进行反向排序。 Use my_dict.items() to get (key, value) tuples.使用my_dict.items()获取 (key, value) 元组。 t[1][1] is the second value. t[1][1]是第二个值。

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

Then sort by the first value.然后按第一个值排序。

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

In current versions of Python, dicts maintain items in key-insertion-order.在当前版本的 Python 中,字典以键插入顺序维护项目。 So you could create a sorted dict by:所以你可以通过以下方式创建一个排序的字典:

my_sorted_dict = dict(items)

using operator.itemgetter()使用 operator.itemgetter()

I don't see a way to use itemgetter on a nested data structure, such as the (key, [value1, value2]) that my_dict.items() provides.我没有看到在嵌套数据结构上使用 itemgetter 的方法,例如 my_dict.items() 提供的 (key, [value1, value2])。 So, to use operator.itemgetter() the structure would need to be flattened.因此,要使用operator.itemgetter()结构需要展平。

import operator

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

This turns it into a tuple of elements like: (k, value1, value2).这会将其变成一个元素元组,例如:(k, value1, value2)。

Now sort the list like before;现在像以前一样对列表进行排序; second element, then first element.第二个元素,然后是第一个元素。 operator.itemgetter(n) creates and returns a function that takes an object and calls __getitem__(n) on that object. operator.itemgetter(n)创建并返回一个 function,它接受一个 object 并在该 object 上调用__getitem__(n) Thus, these lines do a reverse sort keyed by item[2] for each item in items, then a sort keyed by item[1].因此,这些行对 items 中的每个项目进行以 item[2] 为键的反向排序,然后以 item[1] 为键进行排序。

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

Then a dict comprehension builds the sorted dict:然后一个字典理解构建排序的字典:

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

my_sorted_dict my_sorted_dict

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM