Python - 迭代包含字典的列表并解包

18

给定一个由简单字典组成的扁平列表

lst = [{'key1': 1}, {'key2': 2}, {'key3': 3}]

我希望找到产生最小值的字典, 评估方法未在此详细说明. 我的第一个想法是遍历列表逐个检查字典, 但这种方法不起作用:

for k, v in [x.items() for x in lst]:
    print(k, v)

结果为 ValueError(使用生成器而不是列表时):

for k, v in [x.items() for x in lst]:
ValueError: not enough values to unpack (expected 2, got 1)

然而,

for x in lst:
    for k, v in x.items():
        print(k, v)
产生。
key1 1
key2 2
key3 3

正如预期。我假设所有方法都按照预期工作(除非是用户个人误操作),但是为什么使用列表推导式不起作用呢?有人能给我解释一下吗?

编辑:我使用的是Python 3,我知道items()会产生一个dict_view,但我不明白为什么这个逻辑不起作用。


如果您拆开 x.items(),它将返回三个列表,其中包含两个元组(键和值)。如果 x.items() 是礼物,则必须解包另一层礼品包装纸。在您的列表推导式中尝试使用 x.items()[0] - offeltoffel
4个回答

13

你缺少一个迭代级别。

通常,字典拥有多个键/值对。 dict.items() 将整个字典转换为元组序列,格式为 (key, value)。在你的情况下,每个字典只有一个项目,但是 items() 的结果仍然是元组的元组。

如果你打印 [x.items() for x in lst] 的结果,你会看到结果是由 dict_view 项组成的列表;每个都可以被迭代。


没错,就像工作解决方案所显示的那样 - 对我来说也很清楚。我猜我想省略@offeltoffel建议的[0],这似乎有点像魔法数字。为了可读性,我将使用非压缩版本。 - jake77
当尝试解包您的lst时,每个k和v元组都被包装为另一个列表中的唯一项。任何列表中唯一元素的索引是什么?它是0。没有魔法,只有逻辑。虽然我同意可读性比短代码更重要,但您应该实现您感到最舒适的内容。 - offeltoffel

5

如果您不想取得字典视图(dict_view)的第一个元素,可以在列表推导式中增加一层缩进(正如@DanielRoseman所建议的那样):

for k, v in [(k, v) for x in lst for (k, v) in x.items()]:
  print(k, v)

yield

key1 1
key2 2
key3 3

如预期所料。


1

尝试逐步解包lst,以了解它是如何构建的。

>>> in: lst[0].items()
>>> out: [('key1', 1)]

你的结果(等同于列表推导式中的x.items()表达式)是另一个列表,其中包含你的k和v元组。该元组是该列表的索引0处的元素(也是唯一的元素)。因此,你需要按照以下方式进行操作:

for k, v in [x.items()[0] for x in lst]:
    print(k, v)

这行代码不起作用,dict_view 不支持索引。list(x.items())[0] 是可行的方法,但看起来有点丑陋 :-/ - jake77
它在我的电脑上完美运行。不过我使用的是Python 2.7。 - offeltoffel
当然可以,但这是少数几件在升级到3.x版本后会出现问题的事情之一。 - jake77

1
您可以像这样迭代字典的键值对:-

for k, v in dic.items():
    print(k, v)

上面的代码所做的是首先将字典转换为元组列表,然后在迭代到k、v时逐个解包。
k, v = (k, v) # Tuple unpacking.

现在针对您的情况,考虑以下代码:

z = [x.items() for x in lst]
print(z)

输出是
[dict_items([('key1', 1)]), dict_items([('key2', 2)]), dict_items([('key3', 3)])] 

即一个包含元组的列表的列表。

因此,让我们将您的代码重写为:

for k, v in z:
    print(k, v)

其中z是一个元组列表的列表。 在每个迭代中,它从父列表中选择一个列表(该列表仅包含一个元素),然后尝试:

k, v = [(key, value)] # a list of only one tuple to be unpacked against two variables and hence the failure.

希望这对你有所帮助。


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