Как получить ключ словаря по значению из вложенного словаря?

#python #function #dictionary #key #key-value

#python #функция #словарь #Клавиша #ключ-значение

Вопрос:

У меня есть словарь

 game_objects = {
    ('wall', 0): {'position': (0, 0), 'passable': False, 'interactable': False, 'char': '#'},
    ('wall', 1): {'position': (0, 1), 'passable': False, 'interactable': False, 'char': '#'},
    ('player',): {'position': (1, 1), 'passable': True, 'interactable': True, 'char': '@', 'coins': 0},
    ('soft_wall', 11): {'position': (1, 4), 'passable': False, 'interactable': True, 'char': '%'}
}
  

мне нужно создать функцию, которая получит ключ словаря по значению из вложенного словаря. Например:

 get_objects_by_coords((0, 1)) == [('wall', 1)]
get_objects_by_coords((1, 1)) == [('player',)]
get_objects_by_coords((2, 1)) == []
  

Вот что я сделал:

 def get_objects_by_coords(position):
    for position in game_objects.values():
        if position in game_objects.values():
            return game_objects.keys()


print(get_objects_by_coords((0, 0)))
  

но ответ неверен

 dict_keys([('wall', 0), ('wall', 1), ('player',), ('soft_wall', 11)])
  

и мне нужна только эта часть

 [('wall', 1)]
  

итак, как я могу улучшить свой код? Я знаю, что этот код ужасен, но я только учусь

Ответ №1:

Это то, что вы имеете в виду?

 def get_objects_by_coords(position):
    return [key for key, val in game_objects.items()
                for k, v in val.items() if k == 'position' and v == position]

assert get_objects_by_coords((0, 1)) == [('wall', 1)]
assert get_objects_by_coords((1, 1)) == [('player',)]
assert get_objects_by_coords((2, 1)) == []
  

Комментарии:

1. почти, но мне не нужна операция «импорт». Я хотел бы написать правила, но я не могу 🙂 поэтому мне нужно написать код без импорта

2. @Ruslan — этот импорт — просто подсказки типа. Вы можете игнорировать их и удалять все их появления — это не будет иметь значения для кода, по крайней мере, не для ваших целей. Я отредактировал ответ для вашего удобства.

Ответ №2:

Вы возвращаете каждый dict ключ, а не ключ, который вы нашли. Я бы рекомендовал вам взглянуть на dict.items метод, который возвращает пару ключ, значение. Поэтому ваша функция может выглядеть так:

 def get_objects_by_coords(game_objects, position):
    for key, value in game_objects.items():
        if position == value.get('position', (None,)):
            return key
get_objects_by_coords(game_objects, (0, 1)) # == ('wall', 1)
  

Кроме того, если вы собираетесь многократно перебирать словарь в своей программе, я бы не стал использовать структуру данных, как вы, потому что, хотя вы просматриваете ввод dict ключа O (1), итерация по нему для получения значения равна O (n) . Кроме того, я бы не стал использовать глобальную переменную (ваша функция использует game_objects переменную, даже если она не получает ее в качестве аргумента), поскольку это не очень хорошая практика.

Надеюсь, это помогло! Удачи и счастливого кодирования!

Комментарии:

1. Это хороший совет, я прочитаю о методе items, но на сайте, откуда я получил это назначение, происходит сбой кода. Ваш код правильный, но программа на сайте говорит, что это не ответ. Но я думаю, что могу это исправить. Спасибо

Ответ №3:

Возможно, вся ваша структура неверна. Как насчет этого?

 game_objects =  [
    [
        {
            'type':'wall',
            'item_no':0,
            'passsable':False,
            'interacable':False,
            'char':'#'
        },
        
        {
            'type':'wall',
            'item_no':1,
            'passsable':False,
            'interacable':False,
            'char':'#'
        }
    ],
    [
        {
            'type':'player',
            'item_no':None,
            'passable':True,
            'interactable': True,
            'char': '@',
            'coins': 0
        },
        {
            'type':None
        },
        {
            'type':None
        },
        {
            'type':None
        },
        {
            'type':'soft_wall',
            'item_no': 11,
            'passable': False,
            'interactable': True,
            'char': '%'}
    ],
    
]
  

Вывод

 game_objects[1][4]

{'type': 'soft_wall',
 'item_no': 11,
 'passable': False,
 'interactable': True,
 'char': '%'}

game_objects[0][1]

{'type': 'wall',
 'item_no': 1,
 'passsable': False,
 'interacable': False,
 'char': '#'}
  

Комментарии:

1. Не могу изменить структуру словаря, это было по умолчанию