简体   繁体   English

从字典中的列表中查找元素,然后返回该键

[英]Find an element from a list in a dictionary and return that key

If I had someDictionary defined as 如果我将someDictionary定义为

{'1': 33, '2': 44, '3': 55, '4': 10, '5': 66, '6': 60}

and someList defined as someList定义为

[51, 52, 53, 54, 55, 56]

how can I find the key in someDictionary that matches an element in someList ? 如何在someDictionary中找到与someDictionary中的元素匹配的someList For now, I'm assuming there won't be more than one match. 现在,我假设不会有超过一场比赛。

I would think it would be something like this: 我认为应该是这样的:

for k, v in someDictionary.items():
    if v == someList:
        myAnswer = k

Given the code above, myAnswer would be 3 鉴于以上代码, myAnswer3

The second part I need to do is, if someList does not contain an element that is in someDictionary , find the value in someDictionary larger than (but closest to) the last element in someList someList[-1] 第二部分我需要做的是,如果someList不包含在一个元素someDictionary ,找到在价值someDictionary大于(但最接近)在someList的最后一个元素someList[-1]

In that case, myAnswer would be 6 在这种情况下,myAnswer为6

It sounds like you want a bidict 听起来你想要bidict

>>> from bidict import bidict  # pip install bidict
>>> d = bidict({'1': 33, '2': 44, '3': 55, '4': 10, '5': 66, '6': 60})
>>> d['3'] 55
>>> d.inv[55] '3'

This allows O(1) lookups in either direction. 这允许在任一方向上进行O(1)查找。 Now, you can loop over someList and check if an element is in d.inv efficiently. 现在,你可以遍历someList和检查元素是否是in d.inv有效。

First part, Find the list of keys that have a dictionary value in list. 第一部分,找到在列表中具有字典值的键的列表。

someDictionary = {'1': 33, '2': 44, '3': 55, '4': 10, '5': 66, '6': 60}
someList = [51, 52, 53, 54, 55, 56]

res = [key for key, value in someDictionary.items() if value in someList]

second part, if no result from first part, find the key with the closest larger value (continuing): 第二部分,如果没有从第一部分得到的结果,则找到具有最接近的较大值的键(续):

if not res:
    res = min ([(value, key) for key, value in someDictionary.items() if value > max(someList) ])[1]
myAnswer = ''
closest_to = someList[-1]
closest_diff = 0
for k in someDictionary:
    if someDictionary[k] in someList:
         myAnswer = k
         break; # stop the loop when exact match found
    diff = someDictionary[k] - closest_to
    if diff > 0 and diff < closest_diff:
         closest_diff = diff
         myAnswer = k # this would save key of larger but closest number to last in someList

First use list comprehension to gather all keys whose values are in lst , if there is no match then filter for keys whose value is larger than lst[-1] . 首先使用列表lst收集所有值在lst键,如果没有匹配项,则过滤值大于lst[-1] After sort them based on the abs value of the difference of the keys values and the last item in lst and take the 0 index, closest item. 根据键值和lst最后一项之差的abs值对它们进行排序后,取0索引,最接近的项。

dct = {'1': 33, '2': 44, '3': 55, '4': 10, '5': 66, '6': 60}
lst = [51, 52, 53, 54, 55, 56]

my_answer = [int(i) for i in dct if dct[i] in lst]
if my_answer:
    print(*my_answer) # => 3
else:
    close = [i for i in dct if int(dct[i]) > max(lst)]
    closest = sorted(close, key=lambda x: abs(dct.get(x) - lst[-1]))[0]
    print(closest) # => 6

How can I find the key in someDictionary that matches an element in someList ? 如何在someDictionary中找到与someDictionary中的元素匹配的someList

A dictionary is used map keys to values. 字典用于将键映射到值。 The reverse isn't possible in O(1) time. 在O(1)时间内不可能相反。 But you can iterate in O( n ) time until you can match a list element with a dictionary value. 但是您可以在O( n )时间内进行迭代,直到可以将列表元素与字典值匹配为止。

You can use a simple for loop for this, either iterating your dictionary or list. 为此,您可以使用简单的for循环,迭代字典或列表。

d = {'1': 33, '2': 44, '3': 55, '4': 10, '5': 66, '6': 60}
L = [51, 52, 53, 54, 55, 56]

def find_key_dict(d, L):
    L_set = set(L)  # convert to set for O(1) lookup
    for k, v in d.items():
        if v in L_set:
            return k

def find_key_list(d, L):
    d_rev = {v: k for k, v in d.items()}  # reverse dict for value -> key map
    for i in L:
        if i in d_rev:
            return d_rev[i]

find_key_dict(d, L)  # '3'
find_key_list(d, L)  # '3'

It's also possible to rewrite these functions as 1-line generator expressions with next , but this won't necessarily be more efficient. 也可以使用next将这些函数重写为1行生成器表达式,但这不一定会更有效。

The second part I need to do is, if someList does not contain an element that is in someDictionary , find the value in someDictionary larger than (but closest to) the last element in someList 第二部分我需要做的是,如果someList不包含在一个元素someDictionary ,在发现价值someDictionary大于(但最接近)中最后一个元素someList

You can write a similar function utilising a for... else... construct with min : 您可以使用for... else...构造带有min的类似函数:

def find_key_dict(d, L):
    L_set = set(L)  # convert to set for O(1) lookup
    for k, v in d.items():
        if v in L_set:
            return k
    else:
        def min_func(x):
            diff = x[1] - L[-1]
            return diff <= 0, diff
        return min(d.items(), key=min_func)[0]

find_key_dict(d, L)  # '6'

For the first question, you are just using the wrong operator to check if the value is in someList 对于第一个问题,您只是使用错误的运算符来检查值是否在someList

for k, v in someDictionary.items():
    if v in someList:
        myAnswer = k

About the second question you can extend the previous code in this way 关于第二个问题,您可以通过这种方式扩展先前的代码

for k, v in someDictionary.items():
     if v in someList:
         myAnswer = k
         break
else:
     myAnswer = None
     for k, v in someDictionary.items():
         if v > someList[-1] and (myAnswer is None or v < someDictionary[myAnswer]):
             myAnswer = k

If your dictionary and list are large, and especially if you have many lists to test against the same dictionary, it can be worth preparing your data in order to have a faster execution. 如果您的字典和列表很大,尤其是如果您有很多列表要针对同一个字典进行测试,则值得准备数据以便更快地执行。

The worst operation in __init__ is sorting, which is O(n*log(n)). __init__最糟糕的操作是排序,即O(n * log(n))。 It allows us to use bisect to find the closest value in your last case in O(log(n)). 它使我们可以使用bisect在O(log(n))中最后一种情况下找到最接近的值。

from bisect import bisect


class FindInDict:
    def __init__(self, someDictionary):
        self.dict_by_values = {val: key for key, val in someDictionary.items()}
        self.dict_values_set = set(sorted_values)
        self.sorted_values = sorted(someDictionary.values())

    def find(self, someList):
        common = set(someList).intersection(self.dict_values_set)
        if common:
            key = self.dict_by_values[common.pop()]
        else:
            closest_value = self.sorted_values[bisect(self.sorted_values, someList[-1])]
            key = self.dict_by_values[closest_value]
        return key



someDictionary = {'1': 33, '2': 44, '3': 55, '4': 10, '5': 66, '6': 60}    
finder = FindInDict(someDictionary)

finder.find([51, 52, 53, 54, 55, 56])
# 3

finder.find([51, 52, 53, 54, 56])  # no common value
# 6

Here's something that handles both parts of your question and should be easy to modify to handle any pesky "edge-cases" that might pop up: 这可以解决您的问题的两个部分,并且应该易于修改以处理可能弹出的任何讨厌的“边缘情况”:

someDictionary = {'1': 33, '2': 44, '3': 55, '4': 10, '5': 66, '6': 60}
someList = [51, 52, 53, 54, 55, 56]

myAnswer = [key for key in someDictionary if someDictionary[key] in someList]
if not myAnswer:
    diffs = {dict_key: dict_value-someList[-1]
                for dict_key, dict_value in someDictionary.items()
                    if dict_value-someList[-1] > 0}
    myAnswer = [min(diffs, key=diffs.get)]  # Key of value with minimum
                                            # (positive) difference
print(myAnswer)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM