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

Posted

技术标签:

【中文标题】根据列表中的元素对列表作为值的字典进行排序【英文标题】:Sorting a dictionary with lists as values, according to an element from the list 【发布时间】:2010-11-16 01:53:08 【问题描述】:

我想按每个列表中的第三项对列表字典进行排序。当值只是一个数字或字符串时,按值对字典进行排序很容易,但是这个列表让我感到困惑。

例子:

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

我希望能够按每个列表中第三个值的顺序遍历字典,在本例中为 item2item1 然后是 item3

【问题讨论】:

【参考方案1】:

这是一种方法:

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

sorted 函数的key argument 允许您为列表的每个元素派生一个排序键。

要遍历此列表中的键/值,您可以使用以下内容:

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

【讨论】:

我一问这个问题就顿悟了,基本上想出了除了 lambda 之外的相同的东西(还没有了解它们)。刚刚编写了我自己的 cmp 函数,该函数从 dict.items() 接收元组并返回结果。一样的,只是写法不同而已。非常感谢您的快速回复! 很好的解决方案。我喜欢sorted() 的简洁。 我觉得这样更清楚一点:sorted(myDict.items(), key=lambda (k, v): v[2]) @jay, key= 在性能方面比 cmp= 要好得多——而且,礼仪建议您应该接受这个答案,而不是仅仅口头表达感谢!!! "除了 lambda (还没有了解它们" 好点。尽可能避免使用 lambda。这可以使用普通函数 def 来完成,这通常比 lambda 更清晰。 【参考方案2】:

你陈述了两个完全不同的需求:

    “我想做的是对列表字典进行排序......” “我希望能够按...的顺序遍历字典”

根据定义,其中第一个是不可能的——对某物进行排序意味着以某种顺序重新排列。 Python 字典本质上是无序的。第二种可能是模糊的,但极不可能实施。

你能做的是

    复制字典内容(这将是相当 无序) 排序 遍历排序的结果——你已经有了两个 解决方案。顺便说一句,使用“key”的解决方案 “cmp”的更好;见sorted

“列表中的第三项”对我来说闻起来像“元组中的第三项”,而“e[1][2]”只是闻起来:-) ...您可能想使用命名元组进行调查而不是列表;见named tuple factory

如果您要经常对大型数据集进行提取/排序/处理,您可能需要考虑使用 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;

【讨论】:

值得注意的是,从 Python 3.7 开始,dicts 实际上确实保持 insertion 元素的顺序【参考方案3】:

正如 John Machlin 所说,您实际上无法对 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()])]

...这是一个列表理解,它从内部列表理解返回的元组的排序列表中进行 undecorate。内部理解是创建一组元组、您想要的排序键(列表的第三个元素)和与排序键对应的字典键。 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() 的调用中。然后构建 undecorate 表达式(通常就像我在这里展示的一样简单)。

【讨论】:

(1) 您将 decorate-sort-undecorate 与使用 cmp arg 进行比较;关键 arg 的引入切断了 DSU 的一大片领土。 (2)您的解决方案为 OP 留下了 dict 键列表……为了得到他想要的东西,他必须再循环 dict 项(3)您的冗长方式有错字:s/v [2],/v[2], k/【参考方案4】:

现在你可以这样做了;返回字典本身。末尾的布尔值是判断顺序是升序还是降序。

sorted_dict = dict(sorted(myDict.items(), key=lambda item: item[1][2], reverse=True))

【讨论】:

以上是关于根据列表中的元素对列表作为值的字典进行排序的主要内容,如果未能解决你的问题,请参考以下文章

使用Linq根据每个项目中的值的总和对列表进行排序

对具有多个大小值的字典进行排序

根据子列表中的第二个元素按字母顺序对列表进行排序,但不区分大小写[重复]

根据单个对应元素的比率或基于第三个列表对 Python 中的 2 个列表进行排序

我们如何根据 value 中的两个字段对字典<List<int>、List<int>> 进行排序

如何根据 Dart 中的 int 属性对所有 Class 属性进行排序?