列表理解以平整词典词典

时间:2015-01-18 22:18:18

标签: python python-2.7 dictionary list-comprehension

我有一本字典词典:

my_dict = {
    'a': {(1,2): True,
          (1,3): False},
    'b': {(1,4): True,
          (2,3): False}
}

字典总是这种形式,但每个“子”字典都有一组不同的密钥:my_dict['a'][(1,2)]存在,但这并不意味着my_dict['b'][(1,2)]也存在。

我想要一个布尔值的列表(没有特别的顺序):

[True, False, True, False]

我正在尝试使用单个列表理解来完成此任务:

[my_dict[letter][pair] for pair in my_dict[letter] for letter in my_dict]

这会引发错误:

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-142-dc1565efcdc8> in <module>()
      6 }
      7 
----> 8 [my_dict[letter][pair] for pair in my_dict[letter] for letter in my_dict]
KeyError: (2, 3)

它似乎在my_dict ['a']和my_dict ['b']中寻找(2,3)。我认为我写的理解只会在相应的字典中查找键。

我见过this solution可以用来展平任何嵌套字典。我也知道我可以用强制循环来强制它。我只是想弄清楚为什么列表理解不像我写的那样工作。

2 个答案:

答案 0 :(得分:5)

您希望遍历值的值:

[v for nested in outer.itervalues() for v in nested.itervalues()]

请注意,循环需要按照您嵌套的方式进行排序;外循环首先:

for nested in outer.itervalues():
    for v in nested.itervalues():
        # use v
你把订单搞砸了;您的代码仅提供KeyError,因为您预先存在letter全局。

演示:

>>> my_dict = {
...     'a': {(1,2): True,
...           (1,3): False},
...     'b': {(1,4): True,
...           (2,3): False}
... }
>>> [v for nested in my_dict.itervalues() for v in nested.itervalues()]
[True, False, False, True]

答案 1 :(得分:1)

正如埃尔谢比尼所说,

[my_dict[letter][pair] for letter in my_dict for pair in my_dict[letter]]

这也有效:

[little_dict[k] for little_dict in [my_dict[letter] for letter in my_dict] for k in little_dict]

两者都产生[True, False, False, True]

您想了解原始尝试不起作用的原因。

[my_dict[letter][pair] for pair in my_dict[letter] for letter in my_dict]

这个运行的唯一原因是你必须先前已经定义了letter,也许是之前运行过一些类似理解的遗留定义。它首先尝试解释for pair in my_dict[letter],除非letter已经定义,否则无法理解这一点。如果字母先前被定义为b(运行上一个列表理解所留下的值),则它将对设置为my_dict['b']的键。然后,它会查看for letter in my_dict,并将字母设置为'a''b'。然后它会尝试评估第一部分my_dict[letter][pair],但是它使用的是b中的键,因此当字母取值'a'时,这将无效。

下面,我运用你的理解并获得NameError,然后运行另一个理解,作为副作用设置letter的值,然后我再次运行同样的理解并获得{{1} }。

KeyError

请注意,Python 2.6.9 >>> my_dict = { ... 'a': {(1,2): True, ... (1,3): False}, ... 'b': {(1,4): True, ... (2,3): False} ... } >>> >>> [my_dict[letter][pair] for pair in my_dict[letter] for letter in my_dict] Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'letter' is not defined >>> letter Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'letter' is not defined >>> [letter for letter in my_dict] ['a', 'b'] >>> letter 'b' >>> [my_dict[letter][pair] for pair in my_dict[letter] for letter in my_dict] Traceback (most recent call last): File "<stdin>", line 1, in <module> KeyError: (2, 3) >>> 仅在(意外)设置KeyError的值后才会发生letter。第一次运行会生成NameError