HOWTO · Python
在 Python 字典中按值查找键
本教程演示了如何在 Python 字典中按值获取键。
本页内容
Python 字典将键映射到值,因此要根据值查找键,必须搜索字典条目。逐一遍历键值对,并将其中的值与目标值比较。需要第一个匹配键时,可以使用循环或 next();需要所有匹配键时,则可以使用列表推导式。这些搜索会逐项检查条目,直到找到匹配项或遍历完字典。
使用循环搜索键值对
dict.items() 会提供一个可迭代对象,其中包含键值对。遍历它的循环可以返回值等于目标值的第一个键。循环结束后返回 None,可让调用方明确知道没有匹配项;如果 None 本身也可能是有效的键,可以改用独特的哨兵值,或返回 (found, key) 这样的二元组。
运行以下示例:
本节中的代码以及显示的标签或输出仍为英文。
def find_key_by_value(dictionary, target):
for key, value in dictionary.items():
if value == target:
return key
return None
scores = {"Ada": 91, "Lin": 87, "Sam": 91}
print(find_key_by_value(scores, 87))
Lin
找到匹配项后,循环会立即返回,因此结果是按字典迭代顺序遇到的第一个匹配键。如果多个键对应目标值,找到第一个后就不会继续检查后面的匹配项。
使用 next() 获取第一个匹配键
生成器表达式可以简洁地实现相同的首次匹配搜索。将它传给 next() 并提供默认值,这样生成器没有产生匹配键时,调用会返回 None,而不是引发 StopIteration。
将目标值作为参数传入,让表达式既能处理匹配值,也能处理不匹配值:
本节中的代码以及显示的标签或输出仍为英文。
def find_key_with_next(dictionary, target):
return next((key for key, value in dictionary.items() if value == target), None)
scores = {"Ada": 91, "Lin": 87, "Sam": 91}
print(find_key_with_next(scores, 87))
print(find_key_with_next(scores, 100))
生成器会按需产生键,因此不会创建包含所有匹配项的列表。没有值匹配时会返回默认值。如果数据中可能有 None 这个键,请选择一个不会与有效键混淆的默认值。
使用列表推导式收集所有匹配键
如果需要处理重复值,可以用列表推导式收集所有匹配键:
本节中的代码以及显示的标签或输出仍为英文。
def find_all_keys(dictionary, target):
return [key for key, value in dictionary.items() if value == target]
scores = {"Ada": 91, "Lin": 87, "Sam": 91}
print(find_all_keys(scores, 91))
['Ada', 'Sam']
如果没有值匹配,返回的列表为空;否则,列表中会包含所有匹配键。也可以用 filter() 表达式筛选匹配的键值对,不过列表推导式能在一处清楚地展示筛选条件和要收集的键。
通过对齐的键列表和值列表查找键
另一种方法是将 dict.keys() 和 dict.values() 转换为列表。两个列表中的位置一一对应:位置 i 上的键对应位置 i 上的值。在值列表上调用 index(),可以找到目标值首次出现的位置;再用这个位置从键列表中取出对应的键。
本节中的代码以及显示的标签或输出仍为英文。
scores = {"Ada": 91, "Lin": 87, "Sam": 91}
keys = list(scores.keys())
values = list(scores.values())
position = values.index(91)
print(keys[position])
Ada
如果值不存在,index() 会引发 ValueError。因此,可以先检查 values 中是否包含该值,或者在预期值可能不存在时处理这个错误。如果存在重复值,index() 只会选取第一个匹配位置。
处理重复值、缺失值和性能
根据任务选择合适的结果形式:循环或 next() 返回一个键,而列表推导式返回所有匹配键组成的列表。首次匹配方法和 index() 都会在找到第一个匹配项时停止;结果取决于字典的迭代顺序。如果没有匹配项,结果可以是 None 或空列表;对齐列表的方法则会引发 ValueError,除非先检查值是否存在或处理该错误。
这些方法都可能检查每个条目,因此最坏情况下,搜索所需时间与字典条目数成正比。循环和生成器表达式不会创建匹配项集合。列表推导式会创建结果列表;对齐列表的方法则会在搜索前分别创建键列表和值列表。如果需要反复根据值查找键,可以考虑维护反向映射;但要注意重复值,因为简单的反向字典对每个值只会保留一个键。对于嵌套字典,先确定要搜索哪一层,再对该字典应用相同的条目遍历方法。