根据列表中的元素对字典(值为列表)进行排序

54 投票
4 回答
51999 浏览
提问于 2025-04-15 13:19

我想按照每个列表中的第三个元素来给一个字典排序。给字典按值排序的时候,如果值只是一个数字或字符串,那还挺简单的,但这个列表的事情让我感到困惑。

举个例子:

myDict = {'item1': [7, 1, 9], 'item2': [8, 2, 3], 'item3': [9, 3, 11] }

我希望能够按照每个列表中的第三个值来遍历这个字典,在这个例子中,就是 item2item1 然后是 item3

4 个回答

3

正如约翰·马赫林所说,实际上你不能对一个Python字典进行排序。

不过,你可以创建一个键的索引,这个索引可以按照你喜欢的任何顺序进行排序。

在Python中,按照其他标准排序的推荐方法叫做“装饰-排序-去装饰”(DSU)。在这个方法中,你会创建一个临时列表,这个列表包含了你的键和原始数据元素的元组,然后对这个列表调用普通的.sort()方法(或者在更新版本的Python中,直接用sorted()这个内置函数来处理)。最后,你再去掉这些“装饰”。

之所以通常推荐这种方法,而不是直接给.sort()方法传递比较函数,是因为Python内置的默认排序代码(在普通的C Python中是编译成C的)在默认情况下非常快和高效,但在非默认情况下,如果需要多次调用Python对象代码,就会慢得多。因此,通常最好是先遍历数据,创建可以传递给默认排序例程的数据结构。

在这种情况下,你可以使用类似这样的代码:

[y[1] for y in sorted([(myDict[x][2], x) for x in myDict.keys()])]

... 这段代码是一个列表推导式,它从返回的元组排序列表中去掉了装饰。内部的推导式创建了一组元组,包括你想要的排序键(列表的第三个元素)和与排序键对应的字典键。myDict.keys()当然是Python字典的方法,它返回一个有效键的列表,顺序由底层实现决定——大概是简单地遍历哈希值。

一种更详细的做法可能更容易理解:

temp = list()
for k, v in myDict.items():
    temp.append((v[2],))
temp.sort()
results = list()
for i in temp:
    results.append(i[1])

通常你应该在解释器中使用小数据样本逐步构建这样的代码。先构建“装饰”表达式或函数。然后把它包裹在sorted()的调用中。最后构建去装饰的表达式(通常和我这里展示的差不多简单)。

4

你提到的两个需求其实有点不一样:

  1. “我想对一个字典里的列表进行排序...”
  2. “我想按照某种顺序遍历这个字典...”

第一个需求从定义上来说是做不到的——排序意味着要重新排列顺序。而Python的字典本身就是无序的。第二个需求虽然有点可能,但实现起来非常不容易。

你可以做的是:

  1. 先复制字典里的内容(这会是无序的)
  2. 对复制的内容进行排序
  3. 遍历排序后的结果——而且你已经有两种方法可以做到这一点。顺便说一下,使用“key”而不是“cmp”的方法更好;可以参考sorted

提到“列表中的第三个项目”,我觉得这有点像“元组中的第三个项目”,而“e[1][2]”让我觉得有点奇怪 :-) ... 你可能想考虑使用命名元组而不是列表;可以查看命名元组工厂

如果你经常需要对大数据集进行提取、排序和处理,可能可以考虑使用Python自带的sqlite3模块,像这样:

create table ex_dict (k text primary key, v0 int, v1 int, v2 int);
insert into ex_dict values('item1', 7, 1, 9);
-- etc etc 
select * from ex_dict order by v2;
69

这里有一种方法可以做到这一点:

>>> sorted(myDict.items(), key=lambda e: e[1][2])
[('item2', [8, 2, 3]), ('item1', [7, 1, 9]), ('item3', [9, 3, 11])]

sorted 函数的 key 参数 允许你为列表中的每个元素生成一个排序的关键字。

要遍历这个列表中的关键字和值,你可以使用类似下面的代码:

>>> for key, value in sorted(myDict.items(), key=lambda e: e[1][2]):
...   print key, value
... 
item2 [8, 2, 3]
item1 [7, 1, 9]
item3 [9, 3, 11]

撰写回答