当每个键有多个值时,如何根据值获取键列表?
当值是单个对象时,下面的代码可以获取列表。但是,当有多个对象作为值或值中有其他数据时,它无法获取键。
mydict = {
'romeo': 16,
'juliette': 16,
'zena': 'red',
'gabby': 'red',
'lauren': 'smart',
'betty': 'smart',
'kristen': 'sweet',
'lisa': 'sweet',
'lucy': ['smart', 'sweet'],
'shawna': 'green field',
'terry' : 'the green field is on fire',
'dorothy': 'shelly plays on the green field',
'jenny': ['intelligent', 'cuts the smart green field grass'],
}
needle = 'green field'
filtered_keys = [k for k, v in mydict.items() if v == needle]
print(filtered_keys)
当needle = 16
时,输出正确:['romeo', 'juliette']
。
当needle = 'red'
时,输出正确:['zena', 'gabby']
。
当needle = 'smart'
时,输出不正确:['lauren', 'betty']
预期输出为['lauren', 'betty', 'lucy', 'jenny']
。
当needle = 'sweet'
时,输出不正确:['kristen', 'lisa']
预期输出为['kristen', 'lisa', 'lucy']
。
当needle = 'green field'
时,输出不正确:['shawna']
预期输出为['shawna', 'terry', 'dorothy', 'jenny']
。
答案 0 :(得分:1)
当needle
是in
一个in
列表的字符串时,另一个答案无法处理。也就是说,另一个答案仅在needle
等于值或由值直接包含时处理。因此,根据您的问题中包含的测试用例,例如needle = 'green field'
,其他解决方案不起作用。
要概括,您可以递归检查值是否包含needle
。
from typing import Any
from typing import Dict
from typing import Iterable
def keys_containing_value(d: Dict, needle: Any):
def recursively_in(x: Any, n: Any):
if isinstance(x, str) and isinstance(n, str):
return n in x
if type(x) is type(n):
return x == n
if isinstance(x, Iterable) and not isinstance(x, str):
return any(recursively_in(item, n) for item in x)
return [k for k, v in d.items() if recursively_in(v, needle)]
以下是该功能如何使用您的数据和测试用例:
mydict = {
'romeo': 16,
'juliette': 16,
'zena': 'red',
'gabby': 'red',
'lauren': 'smart',
'betty': 'smart',
'kristen': 'sweet',
'lisa': 'sweet',
'lucy': ['smart', 'sweet'],
'shawna': 'green field',
'terry': 'the green field is on fire',
'dorothy': 'shelly plays on the green field',
'jenny': ['intelligent', 'cuts the smart green field grass'],
}
needles = [
16,
'red',
'smart',
'sweet',
'green field',
]
for needle in needles:
print(keys_containing_value(mydict, needle))
<强>输出:强>
['romeo', 'juliette']
['zena', 'gabby']
['lauren', 'betty', 'lucy', 'jenny']
['kristen', 'lisa', 'lucy']
['shawna', 'terry', 'dorothy', 'jenny']
答案 1 :(得分:0)
你有几个选择。我建议您只将所有dict
值包装在列表中。所以你的dict
将是:
mydict = {'romeo':[16],
'juliette':[16],
'zena': ['red'],
'gabby': ['red'],
'lauren': ['smart'],
'betty': ['smart'],
'kristen': ['sweet'],
'lisa': ['sweet'],
'lucy': ['smart', 'sweet'],
'shawna': ['green field'],
'terry' :['the green field is on fire'],
'dorothy' :['shelly plays on the green field'],
'jenny': ['intelligent', 'cuts the smart green field grass'],
}
然后你的列表理解将如下所示:
list_keys = [key for key, val in mydict.items() if lvalue in val]
另一种选择是测试dict
中的值的类型。我不建议这样做,但如果您的情况不允许以前的解决方案,这可能会有效。因此,您的列表理解将如下所示:
list_keys = [key for key, val in mydict.items() if (type(val)==list and lvalue in val) or lvalue==val]
这里的问题是,如果您的dict
值得到其他类型的可迭代,那么您必须更改代码以检查其他可迭代类型。只检查值是否是可迭代的工作是不可行的,因为当你检查string
的值时,你会遇到其他问题。 'green' in 'green sleeves'
评估为True
的内容即使(基于您在问题中显示的内容),我认为您希望将其评估为False
。