hex93
hex93

Reputation: 359

Getting the key from a value within a dict of dicts

I have a dict of dicts dict_of_dicts={1:{'id':1,'name':'joe'},2: {'id':2,'name':'jim'},3: {'id':3,'name':'bob'}} (the structure is out of my control so I cannot define my dict more conveniently). I am looking to extract the id # (which also corresponds to the key of the upper dict) of the sub dict containing 'name':'bob'. i.e I want to extract the id value for a specific name.

I have thought of a looping solution, but is there a more pythonic way to go about this? My attempt is below

for i in list(dict_of_dicts.values()):
    if i['name']=='bob':
        print(i['id'])

Upvotes: 1

Views: 76

Answers (6)

alkanen
alkanen

Reputation: 655

You can use next() to find the first instance in a generator that satisfy your needs:

dict_of_dicts = {
    1: {
        'id': 1,
        'name': 'joe'
    },
    2: {
        'id': 2,
        'name': 'jim'
    },
    3: {
        'id': 3,
        'name': 'bob'
    }
}

# Find "bob"
try:
    id_bob = next(
        dict_of_dicts[key]["id"]
        for key in dict_of_dicts
        if dict_of_dicts[key]["name"] == "bob"
    )
except StopIteration:
    print("'bob' not found, handle this some way")
    raise

# bob_id == 3

If you know for sure that "id" is the same value as the key, just use key instead of dict_of_dicts[key]["id"].

Upvotes: 0

Synthaze
Synthaze

Reputation: 6090

A one-liner:

d={1:{'id':1,'name':'joe'},2: {'id':2,'name':'jim'},3: {'id':3,'name':'bob'}}

print ([ k for k,v in d.items() if 'bob' in v['name'] ])

Output:

[3]

Here you get a list of keys/id in case you have multiple ids with `'name':'bob'.

Upvotes: 0

sushanth
sushanth

Reputation: 8302

Here is solution you can try out,

search_ = 'bob'

for k, v in dict_of_dicts.items():
    if search_ in v.values():
        print(f"Id {k}")
        break
else:
    print("No Match Found")

Edit

def search_(key):
    for k, v in dict_of_dicts.items():
        if key in v.values():
            return k
        
    return -1  # Indicating no match found

Upvotes: 2

Danish Shrestha
Danish Shrestha

Reputation: 487

Alternatively you could use filter function by passing a lambda that resolves to True if the name matches the search criteria. I passed in a default value of {'id': None} when grabbing the first item using next item if there are no match.

filtered = filter(lambda x: x['name'] == 'bob', dict_of_dicts.values())
match = next(filtered, {'id': None})
print(match['id'])

Upvotes: 0

William
William

Reputation: 373

for k, v in dict_of_dicts.items():
    if v["name"] == "bob":
       print(v["id"])

You can also just print(k)

Upvotes: 1

Andreas
Andreas

Reputation: 9197

Even if the structure is out of your control, in case you want to have multiple searches, it might make sense to reformat the data before searchign multiple times, you can match the results later again if needed:

d = {1:{'id':1,'name':'joe'},2: {'id':2,'name':'jim'},3: {'id':3,'name':'bob'}}

n = {e['name']:e['id'] for e in d.values()}

n.get('bob')
#Out[32]: 3

Upvotes: 0

Related Questions