当每个键有多个值时,根据值获取键列表

时间:2018-06-13 18:39:20

标签: python python-3.x dictionary

当每个键有多个值时,如何根据值获取键列表?

当值是单个对象时,下面的代码可以获取列表。但是,当有多个对象作为值或值中有其他数据时,它无法获取键。

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']

2 个答案:

答案 0 :(得分:1)

needlein一个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