Если бы у меня был someDictionary, определенный как
{'1': 33, '2': 44, '3': 55, '4': 10, '5': 66, '6': 60}
и someList, определенный как
[51, 52, 53, 54, 55, 56]
как я могу найти ключ в someDictionary, который соответствует элементу в someList? На данный момент я предполагаю, что будет не более одного матча.
Я бы подумал, что это будет примерно так:
for k, v in someDictionary.items():
if v == someList:
myAnswer = k
Учитывая приведенный выше код, myAnswer будет 3.
Вторая часть, которую мне нужно сделать, это, если someList не содержит элемента, который находится в someDictionary, найти значение в someDictionary больше, чем (но ближе всего к) последний элемент в someList someList[-1]
В этом случае myAnswer будет 6.
@Stephen, извини, я ввожу someList; ищет любой элемент в someList, который соответствует значению в someDictionary. 55 в someList соответствует значению в someDictionary с ключом 3
Вы имеете ввиду ключ '3'? 3 - это не ключ твоего дикта.
С учетом замечаний, мне нужно поработать над тем, чтобы лучше сформулировать свои вопросы, извините.






Первая часть, найдите список ключей, которые имеют словарное значение в списке.
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]
вторая часть, если нет результата от первой части, найдите ключ с ближайшим большим значением (продолжение):
if not res:
res = min ([(value, key) for key, value in someDictionary.items() if value > max(someList) ])[1]
Благодарность; похоже, это возвращает список ['3']. Есть ли простой способ вернуть вместо этого int?
если вы знаете, что все ключи имеют тип int, вы можете изменить [ключ для ключа ..] на [int (ключ) для ключа ...
Это список, потому что он обрабатывает случай, когда есть более одного совпадения, если вам просто нужен первый элемент, вы можете перейти к res [0].
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
Я ценю это!
Сначала используйте понимание списка, чтобы собрать все ключи, значения которых находятся в lst, если нет совпадения, отфильтруйте ключи, значение которых больше, чем lst[-1]. После отсортируйте их по абсолютному значению разницы значений ключей и последнего элемента в lst и возьмите индекс 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
someDictionarythat matches an element insomeList?
Словарь используется для сопоставления ключей со значениями. Обратное невозможно за время O (1). Но вы можете выполнять итерацию за время O (п), пока не сможете сопоставить элемент списка со значением словаря.
Вы можете использовать для этого простой цикл 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'
Также можно переписать эти функции как выражения генератора в одну строку с помощью next, но это не обязательно будет более эффективным.
The second part I need to do is, if
someListdoes not contain an element that is insomeDictionary, find the value insomeDictionarylarger than (but closest to) the last element insomeList
Вы можете написать аналогичную функцию, используя конструкцию 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'
Спасибо! Преобразование списка в набор пока работает хорошо. Я все еще ищу остальное ..
Что касается первого вопроса, вы просто используете неправильный оператор, чтобы проверить, находится ли значение в someList.
for k, v in someDictionary.items():
if v in someList:
myAnswer = k
По поводу второго вопроса вы можете расширить предыдущий код таким образом
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
ну черт. Мне просто нужно было использовать in :) Спасибо!
Я, вероятно, буду пересматривать этот пост много раз, когда начну писать код для крайних случаев; но это отвечает на мой вопрос. Спасибо!
>>> 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'
Это позволяет выполнять поиск О (1) в любом направлении. Теперь вы можете перебрать someList и проверить, действительно ли элемент является in d.inv.
Если ваш словарь и список большие, и особенно если у вас есть много списков для тестирования по одному и тому же словарю, возможно, стоит подготовить ваши данные, чтобы ускорить выполнение.
Худшая операция в __init__ - это сортировка, которая равна O (n * 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
Вот что-то, что обрабатывает обе части вашего вопроса и должно быть легко изменено для обработки любых надоедливых "крайних случаев", которые могут появиться:
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)
Немного запутался в вашем ответе
3. Вы вводили55или вы вводилиsomeList? Вам нужен список ключей, которые соответствуют значениям вsomeList?