如果存在键,则按键对Python字典列表进行排序

9

我有一个像这样的字典列表:

[{"foo" : "bar", "myKey" : "one"}, 
{"foo" : "bar", "myKey" : "two"}, 
{"foo" : "bar", "yourKey" : "three"}]

如果字典中存在键,我希望你能按照该键对其进行排序。
featured = sorted(filesToWrite, key=lambda k: k["myKey"])

如果"myKey"不存在,这是无法正常工作的。 编辑: 如果字典中没有myKey,我希望它出现在列表的末尾。

我可以手动遍历列表并自己完成,但我相信有一种Pythonic的方法可以实现我的目标而无需进行所有操作。

4个回答

19

来看一下dict.get函数:

featured = sorted(filesToWrite, key=lambda k: ("myKey" not in k, k.get("myKey", None)))

输出:

[{'foo': 'bar', 'myKey': 'one'}, {'foo': 'bar', 'myKey': 'two'}, {'yourKey': 'three', 'foo': 'bar'}]

魔法发生在这个关键点:

("myKey" in k, k.get("myKey", None)

这是一个包含两个项目的元组,例如:

(True, "one")

第一个元素是True或False,取决于键是否丢失(True在False之后,因此使用not),第二个元素是该键的值(如果存在)。如果不存在,则为None。(可以跳过该参数,但我包含它是为了明确)


困惑。我完全不需要你的Key...我只希望任何没有"myKey"的东西都应该在最后。 - Brad

1
如果你真的遇到了困难(就像我一样,由于我尝试排序的数据结构),你可能想要退出 lambda 设计,至少出于诊断目的。只有当我应用这里所示的 "nonesorter" design 时,我才收到来自 Python 的有意义的诊断,它向我展示了我正在排序的事物并非我所认为的那样。
更一般地说:你在上面看到的 "lambda" 是一种简写形式,可以用完整的方法定义替换,你可以通过调试器逐行跟踪。
此外,对于新手来说有些误导的是 Python 排序语法中的标签 key=。这实际上不是字典中键字段的名称,而是一个指向函数的指针,该函数将确定顺序,类似于 Perl 的 sort 参数称为 SUBNAME
正如Python.org 的排序 HOW TO 所描述的那样,

key参数的值应该是一个函数,它接受一个参数并返回用于排序的键。这种技术非常快速,因为对于每个输入记录,关键函数仅被调用一次。

最后,请注意,正如其他人所述,None在Python 2中是一个合法的比较项,而在Python 3中尝试与None进行比较会生成编译器异常。


0
>>> L = [{"foo" : "bar", "myKey" : "one"}, 
... {"foo" : "bar", "myKey" : "two"}, 
... {"foo" : "bar", "yourKey" : "three"}]
>>> 
>>> sorted(L, key=lambda d:("myKey" not in d, d.get("myKey")))
[{'foo': 'bar', 'myKey': 'one'}, {'foo': 'bar', 'myKey': 'two'}, {'yourKey': 'three', 'foo': 'bar'}]

不行。这对于UTF-8或非字符串值无效。这不必要地依赖于sorted()的某些行为。 - IceArdor
@IceArdor,是的,我删除了第二种方法。不确定您所说的依赖于“sorted”的行为是什么意思。毕竟这是有文档记录的行为。 - John La Rooy
使用 sorted(L, key=lambda d:d.get("myKey","\xff")) 依赖于 sorted 如何将 ASCII 字符串与非 ASCII 字符串或非字符串进行比较。虽然我的 Jython 版本恰好在字符串之前对 None 和数字进行排序,但这可能会在未来发生变化。我个人不想追踪错误以发现程序员依赖于 sorted 的数据类型优先级解释。 - IceArdor

0

关于什么?

sorted((e for e in case if 'myKey' in e), key=lambda x: x['myKey']) + [e for e in case if 'myKey' not in e]

假设“case”变量保存了你刚提到的字典列表。我还假设如果键不存在,它应该被忽略,这似乎是有道理的。


这需要两次循环遍历字典。效率低下。 - IceArdor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接