15

给定一个简单字典的平面列表

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

正如预期的那样。我假设所有方法都按预期工作(除非 PEBKAC),但为什么它不能使用列表理解?有人可以启发我吗?

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

4

4 回答 4

11

你错过了一个迭代级别。

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

如果你打印结果,[x.items() for x in lst]你会看到结果是一个dict_view项目列表;其中每一个本身都可以迭代。

于 2017-09-21T14:00:16.480 回答
5

dict_view您可以在列表理解中添加一层缩进(如@DanielRoseman 建议的那样),而不是采用您的第一个元素:

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

屈服

key1 1
key2 2
key3 3

正如预期的那样。

于 2017-09-21T14:32:40.060 回答
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)
于 2017-09-21T14:04:37.807 回答
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.

我希望这可以帮到你。

于 2017-09-21T14:31:46.203 回答