列表理解以展平字典的字典
List Comprehension to Flatten a Dictionary of Dictionaries
我有一本字典的字典:
my_dict = {
'a': {(1,2): True,
(1,3): False},
'b': {(1,4): True,
(2,3): False}
}
字典总是这种形式,但每个 'child' 字典都有一组不同的键: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 可以展平任何嵌套字典。我也知道我可以用命令式循环暴力破解它。我只是想了解为什么列表理解没有按照我写的方式工作。
您想遍历值的值:
[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
global.
演示:
>>> 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]
正如 elsherbini 所说,
[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
已经定义,否则无法理解这一点。如果 letter 之前被定义为 b
(运行ning 之前的列表理解遗留下来的值),那么它将 pair 设置为 my_dict['b']
的键。然后它查看 for letter in my_dict
并将字母设置为 'a'
和 'b'
。然后它尝试计算第一部分 my_dict[letter][pair]
,但它使用的是 b
中的键,因此当字母取值 'a'
.
时这将不起作用
下面,我 运行 你的理解并得到 NameError
,然后 运行 另一个理解作为副作用设置 letter
的值,然后我 运行 你同样的理解再次得到 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
。
我有一本字典的字典:
my_dict = {
'a': {(1,2): True,
(1,3): False},
'b': {(1,4): True,
(2,3): False}
}
字典总是这种形式,但每个 'child' 字典都有一组不同的键: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 可以展平任何嵌套字典。我也知道我可以用命令式循环暴力破解它。我只是想了解为什么列表理解没有按照我写的方式工作。
您想遍历值的值:
[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
global.
演示:
>>> 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]
正如 elsherbini 所说,
[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
已经定义,否则无法理解这一点。如果 letter 之前被定义为 b
(运行ning 之前的列表理解遗留下来的值),那么它将 pair 设置为 my_dict['b']
的键。然后它查看 for letter in my_dict
并将字母设置为 'a'
和 'b'
。然后它尝试计算第一部分 my_dict[letter][pair]
,但它使用的是 b
中的键,因此当字母取值 'a'
.
下面,我 运行 你的理解并得到 NameError
,然后 运行 另一个理解作为副作用设置 letter
的值,然后我 运行 你同样的理解再次得到 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
。