简体   繁体   中英

How to get a dictionary key by value from a nested dictionary?

I have a dictionary

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': '%'}
}

i need to make a function which will get a dictionary key by value from a nested dictionary. For example:

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

Here is what i did:

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)))

but the answer is not correct

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

and I need only this part

[('wall', 1)]

so, how can I improve my code? I know this code is awful, but I'm just learning

You are returning every dict key, and not the key you found. I would recommend you to take a look into dict.items method, which return a pair of key, value. Therefore, your function could look like:

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)

Also, if you are going to iterate many times over the dictionary in your program, I wouldn't use the Data Structure as you did, because although looking into a dict key i O(1), iterating over it to get to a value is O(n). Furthermore, I wouldn't use a global variable (you function uses game_objects variable even though it doesn't receives it as an argument), as it's not a good practice.

Hope this helped! Good luck, and happy coding!

Is this what you mean?

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)) == []

Maybe your entire structure is wrong. What about this?

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': '%'}
    ],
    
]

Output

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': '#'}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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