【问题标题】:python - iterating list of dictionaries and unpackingpython - 迭代字典列表和解包
【发布时间】:2017-09-21 13:53:46
【问题描述】:

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

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

我想找到使用此处未详述的方法评估的最小值的 dict。 我的第一个想法是迭代列表以逐个检查字典,但这失败了:

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 但我不明白为什么逻辑不起作用。

【问题讨论】:

  • 如果你解压x.items(),它会返回三个列表,其中包含两个(键和值)的元组。如果x.items() 是礼物,您必须打开另一层礼品包装纸。在您的列表理解中尝试x.items()[0]

标签: python python-3.x list-comprehension argument-unpacking


【解决方案1】:

您缺少一个迭代级别。

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

如果您打印[x.items() for x in lst] 的结果,您会看到结果是dict_view 项目的列表;每一个都可以自己迭代。

【讨论】:

  • 对,从工作解决方案中很清楚 - 对我来说也是如此。我想我想省略@offeltoffel 建议的 [0],看起来有点像一个神奇的数字。为了便于阅读,我将使用非理解版本。
  • 在尝试解压缩lst 时,k 和 v 的每个元组都被包装为另一个列表中的唯一项目。任何列表中唯一元素的索引是多少?这是0。没有魔法,只有逻辑。我同意可读性比短代码更重要,所以你应该实现你觉得最舒服的任何东西。
【解决方案2】:

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

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

正如预期的那样。

【讨论】:

    【解决方案3】:

    您可以像这样遍历字典的键、值对:-

    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.
    

    我希望这会有所帮助。

    【讨论】:

      【解决方案4】:

      尝试逐步解压您的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] 是要走的路,但看起来很难看:-/
      • 它在我的机器上运行良好。不过我使用的是 python 2.7。
      • 当然,但是如果您转到 3.x,这是少数会中断的事情之一
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-09-26
      • 1970-01-01
      • 1970-01-01
      • 2021-02-22
      • 2020-07-12
      • 2014-05-29
      • 2015-09-28
      相关资源
      最近更新 更多