如何在 Python 的字典中请求子键的键?
How can I ask for a key of a subkey in a dictionary in Python?
如果我有一个字典中的一个字典,我如何在恒定时间内请求一个键?
例如:
def get_hobby(hobby):
d = {'An' : {'Hobby': "Paintball", 'Age' : 22}, 'Jef' : {'Hobby' : "Football", 'Age': 24}, 'Jos' : {'Hobby': "Paintball", 'Age' : 46}}
assert get_hobby("Paintball") == ['An', 'Jos']
这行不通:
return d.keys[hobby]
这应该有效:
return [key for key, val in d.items() if val['Hobby'] == hobby]
例如:
def get_hobby(hobby):
d = {
'An': {'Hobby': "Paintball", 'Age' : 22},
'Jef': {'Hobby' : "Football", 'Age': 24},
'Jos' : {'Hobby': "Paintball", 'Age' : 46}
}
return [key for key, val in d.items() if val['Hobby'] == hobby]
print get_hobby("Paintball")
结果:
['Jos', 'An']
使用列表理解:
return [name for name, props in d.items() if props['Hobby'] == hobby]
d.items()
给你一个 (key, value)
对的序列,其中值是嵌套字典。列表理解通过将 hobby
变量与嵌套的 'Hobby'
键匹配来过滤这些,生成过滤器测试 returns True
.[=20 的名称列表=]
你不能在常数时间内要求钥匙,因为那个数字是可变的。
演示:
>>> def get_hobby(hobby):
... d = {'An' : {'Hobby': "Paintball", 'Age' : 22}, 'Jef' : {'Hobby' : "Football", 'Age': 24}, 'Jos' : {'Hobby': "Paintball", 'Age' : 46}}
... return [name for name, props in d.items() if props['Hobby'] == hobby]
...
>>> get_hobby("Paintball")
['Jos', 'An']
请注意,returned 键列表是任意顺序,因为字典没有固定顺序。您不能简单地针对另一个列表测试该列表并期望它每次都相等,因为列表确实有顺序。具体顺序取决于Python hash seed和字典的插入和删除历史。
您可能想要 return 一个 设置 ;集合也没有顺序,更好地反映了匹配键的性质 returned:
return {name for name, props in d.items() if props['Hobby'] == hobby}
之后您的断言将变为:
assert get_hobby("Paintball") == {'An', 'Jos'}
如果您需要在恒定时间内进行大量此类查询,则必须更改为适当的数据结构。例如:
d2 = {}
for name, subdict in d.items():
for key, value in subdict:
d2.setdefault((key, value), set()).add(name)
(请注意,我使用了 set
,而不是 list
; 解释了原因。)
现在:
d2['Hobby', 'Paintball']
简单、高效。
当然,构建数据结构并不需要常数时间;它显然必须遍历整个字典中每个元素的每个子元素。但是你只做一次,然后你所有的不计其数的查询都是恒定的时间。所以,只要你买得起space,而"zillion"其实是一个很大的数字,这就是你想要的优化。
您将需要重组您的代码,这样 dict 实际上 是 构建一次,而不是每次 get_hobbies
被调用。这是否意味着将它放在 class 中,使用闭包,显式记忆存储在函数上的属性,或者只使用在顶层构建的全局变量,由您决定。拿最后一个,只因为它最短(可能不是最好的):
d = {'An' : {'Hobby': "Paintball", 'Age' : 22}, 'Jef' : {'Hobby' : "Football", 'Age': 24}, 'Jos' : {'Hobby': "Paintball", 'Age' : 46}}
d2 = {}
for name, subdict in d.items():
for key, value in subdict:
d2.setdefault((key, value), set()).add(name)
def get_hobby(hobby):
return d2['Hobby', hobby]
assert get_hobby("Paintball") == {'An', 'Jos'}
如果我有一个字典中的一个字典,我如何在恒定时间内请求一个键? 例如:
def get_hobby(hobby):
d = {'An' : {'Hobby': "Paintball", 'Age' : 22}, 'Jef' : {'Hobby' : "Football", 'Age': 24}, 'Jos' : {'Hobby': "Paintball", 'Age' : 46}}
assert get_hobby("Paintball") == ['An', 'Jos']
这行不通:
return d.keys[hobby]
这应该有效:
return [key for key, val in d.items() if val['Hobby'] == hobby]
例如:
def get_hobby(hobby):
d = {
'An': {'Hobby': "Paintball", 'Age' : 22},
'Jef': {'Hobby' : "Football", 'Age': 24},
'Jos' : {'Hobby': "Paintball", 'Age' : 46}
}
return [key for key, val in d.items() if val['Hobby'] == hobby]
print get_hobby("Paintball")
结果:
['Jos', 'An']
使用列表理解:
return [name for name, props in d.items() if props['Hobby'] == hobby]
d.items()
给你一个 (key, value)
对的序列,其中值是嵌套字典。列表理解通过将 hobby
变量与嵌套的 'Hobby'
键匹配来过滤这些,生成过滤器测试 returns True
.[=20 的名称列表=]
你不能在常数时间内要求钥匙,因为那个数字是可变的。
演示:
>>> def get_hobby(hobby):
... d = {'An' : {'Hobby': "Paintball", 'Age' : 22}, 'Jef' : {'Hobby' : "Football", 'Age': 24}, 'Jos' : {'Hobby': "Paintball", 'Age' : 46}}
... return [name for name, props in d.items() if props['Hobby'] == hobby]
...
>>> get_hobby("Paintball")
['Jos', 'An']
请注意,returned 键列表是任意顺序,因为字典没有固定顺序。您不能简单地针对另一个列表测试该列表并期望它每次都相等,因为列表确实有顺序。具体顺序取决于Python hash seed和字典的插入和删除历史。
您可能想要 return 一个 设置 ;集合也没有顺序,更好地反映了匹配键的性质 returned:
return {name for name, props in d.items() if props['Hobby'] == hobby}
之后您的断言将变为:
assert get_hobby("Paintball") == {'An', 'Jos'}
如果您需要在恒定时间内进行大量此类查询,则必须更改为适当的数据结构。例如:
d2 = {}
for name, subdict in d.items():
for key, value in subdict:
d2.setdefault((key, value), set()).add(name)
(请注意,我使用了 set
,而不是 list
;
现在:
d2['Hobby', 'Paintball']
简单、高效。
当然,构建数据结构并不需要常数时间;它显然必须遍历整个字典中每个元素的每个子元素。但是你只做一次,然后你所有的不计其数的查询都是恒定的时间。所以,只要你买得起space,而"zillion"其实是一个很大的数字,这就是你想要的优化。
您将需要重组您的代码,这样 dict 实际上 是 构建一次,而不是每次 get_hobbies
被调用。这是否意味着将它放在 class 中,使用闭包,显式记忆存储在函数上的属性,或者只使用在顶层构建的全局变量,由您决定。拿最后一个,只因为它最短(可能不是最好的):
d = {'An' : {'Hobby': "Paintball", 'Age' : 22}, 'Jef' : {'Hobby' : "Football", 'Age': 24}, 'Jos' : {'Hobby': "Paintball", 'Age' : 46}}
d2 = {}
for name, subdict in d.items():
for key, value in subdict:
d2.setdefault((key, value), set()).add(name)
def get_hobby(hobby):
return d2['Hobby', hobby]
assert get_hobby("Paintball") == {'An', 'Jos'}