получение ключа dict с использованием значения dict в python - PullRequest
1 голос
/ 24 ноября 2011

Мой вопрос: как получить ключ словаря, используя значение словаря?

d={'dict2': {1: 'one', 2: 'two'}, 'dict1': {3: 'three', 4: 'four'}}

Я хочу получить dict2 ключ от ключа two.

Спасибо.

Ответы [ 7 ]

2 голосов
/ 24 ноября 2011

Вот рекурсивное решение, которое может обрабатывать произвольно вложенные словари:

>>> import collections
>>> def dict_find_recursive(d, target):
...     if not isinstance(d, collections.Mapping):
...         return d == target
...     else:
...         for k in d:
...             if dict_find_recursive(d[k], target) != False:
...                 return k
...     return False

В долгосрочной перспективе это не так эффективно, как «обратный словарь», но если вы не выполняете такие обратные поиски часто,это, вероятно, не имеет значения.(Обратите внимание, что вы должны явно сравнить результат dict_find_recursive(d[k], target) с False, потому что в противном случае ложные ключи, такие как '', приводят к сбою поиска. На самом деле, даже эта версия не срабатывает, если в качестве ключа используется False;Полностью общее решение будет использовать уникальный часовой object() для обозначения фальши.)

Несколько примеров использования:

>>> d = {'dict1': {3: 'three', 4: 'four'}, 'dict2': {1: 'one', 2: 'two'}}
>>> dict_find_recursive(d, 'two')
'dict2'
>>> dict_find_recursive(d, 'five')
False
>>> d = {'dict1': {3: 'three', 4: 'four'}, 'dict2': {1: 'one', 2: 'two'}, 
         'dict3': {1: {1:'five'}, 2: 'six'}}
>>> dict_find_recursive(d, 'five')
'dict3'
>>> dict_find_recursive(d, 'six')
'dict3'

Если вы хотите отменить произвольно вложенный набор словарей, рекурсивные генераторыВаш друг:

>>> def dict_flatten(d):
...     if not isinstance(d, collections.Mapping):
...         yield d
...     else:
...         for value in d:
...             for item in dict_flatten(d[value]):
...                 yield item
... 
>>> list(dict_flatten(d))
['three', 'four', 'five', 'six', 'one', 'two']

Выше просто перечисляются все значения в словаре, которые не являются отображениями.Затем вы можете сопоставить каждое из этих значений с ключом, например, так:

>>> def reverse_nested_dict(d):
...     for k in d:
...         if not isinstance(d[k], collections.Mapping):
...             yield (d[k], k)
...         else:
...             for item in dict_flatten(d[k]):
...                 yield (item, k)
... 

Это генерирует итеративный набор кортежей, поэтому информация не теряется:

>>> for tup in reverse_nested_dict(d):
...     print tup
... 
('three', 'dict1')
('four', 'dict1')
('five', 'dict3')
('six', 'dict3')
('one', 'dict2')
('two', 'dict2')

Если вы знаете, что всеваши не отображаемые значения могут быть хэшируемыми - и если вы знаете, что они уникальны, или если вам не нужны коллизии - просто передайте получившиеся кортежи в dict():

>>> dict(reverse_nested_dict(d))
{'six': 'dict3', 'three': 'dict1', 'two': 'dict2', 'four': 'dict1', 
 'five': 'dict3', 'one': 'dict2'}
1 голос
/ 24 ноября 2011

Следующее создаст обратный словарь для двухуровневого примера:

d={'dict2': {1: 'one', 2: 'two'}, 'dict1': {3: 'three', 4: 'four'}}
r = {}
for d1 in d:
    for d2 in d[d1]:
        r[d[d1][d2]] = d1

Результат:

>>> r
{'four': 'dict1', 'three': 'dict1', 'two': 'dict2', 'one': 'dict2'}
1 голос
/ 24 ноября 2011

Если вы не хотите переворачивать словарь, вот другое возможное решение:

def get_key_from_value(my_dict, v):
    for key,value in my_dict.items():
        if value == v:
            return key
    return None

>>> d = {1: 'one', 2: 'two'}
>>> get_key_from_value(d,'two')
2
0 голосов
/ 20 мая 2014

вот пример, о котором никто не задумывается: (может использоваться аналогично)

raw_dict = { 'key1': 'val1', 'key2': 'val2', 'key3': 'val1' }

new_dict = {}
for k,v in raw_dict.items():
    try: new_dict[v].append(k)
    except: new_dict[v] = [k]

результат:

>>> new_dict
{'val2': ['key2'], 'val1': ['key3', 'key1']}

возможно, не самый лучший из методов, но он работает для того, для чего он мне нужен.

0 голосов
/ 27 января 2012

Для обработки вложенных словарей я бы сделал так же, как ответ отправителя .

Однако, если в будущем он не будет содержать вложенные словари, будьте очень осторожны, делая простое обращение. По своему дизайну словарь ключей уникален, но значения не имеют этого требования.

Если у вас есть значения, которые одинаковы для нескольких ключей, при обращении к словарю вы потеряете всех, кроме одного из них. А поскольку словари не отсортированы, вы можете потерять разные данные произвольно.

Пример работы с реверсом:

>>> d={'dict1': 1, 'dict2': 2, 'dict3': 3, 'dict4': 4}
>>> rd = dict([(v,k) for k,v in d.items()])
>>> print d
{'dict4': 4, 'dict1': 1, 'dict3': 3, 'dict2': 2}

>>> print rd
{1: 'dict1', 2: 'dict2', 3: 'dict3', 4: 'dict4'}  

Пример неудачного обращения: обратите внимание, что dict4 потеряно

>>> d={'dict1': 1, 'dict2': 4, 'dict3': 3, 'dict4': 4}
>>> rd = dict([(v,k) for k,v in d.items()])
>>> print d
{'dict4': 4, 'dict1': 1, 'dict3': 3, 'dict2': 4}

>>> print rd
{1: 'dict1', 3: 'dict3', 4: 'dict2'}
0 голосов
/ 24 ноября 2011

Напишите код для обращения к словарю (т. Е. Создайте новый словарь, который сопоставит значения старого с ключами старого).
Поскольку вы, похоже, имеете дело с вложенными словарями, это, очевидно, будет сложнее,Выясните наименьшее, что вам нужно, чтобы решить вашу проблему, и запишите ее (т.е. не создавайте решение, которое будет работать с произвольной глубиной вложенности, если ваша проблема имеет дело только с диктовками в диктовках, которые в свою очередь не имеют диктов)

0 голосов
/ 24 ноября 2011

Я не знаю о лучшем решении, но одна возможность - перевернуть словарь (чтобы значения стали ключами), а затем просто выполнить обычный поиск ключей. Это обратит словарь:

forward_dict = { 'key1': 'val1', 'key2': 'val2'}
reverse_dict = dict([(v,k) for k,v in forward_dict.items()])

Итак, учитывая "val1", я могу просто сделать:

reverse_dict["val1"]

чтобы найти соответствующий ключ. Есть очевидные проблемы с этим решением - например, если ваши значения не являются уникальными, вы потеряете некоторую информацию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...