Accessing Python dict values with the key start characters

Question:

I was wondering: would it be possible to access dict values with uncomplete keys (as long as there are not more than one entry for a given string)? For example:

my_dict = {'name': 'Klauss', 'age': 26, 'Date of birth': '15th july'}
print my_dict['Date']
>> '15th july'

Is this possible? How could it be done?

Asked By: Roman Rdgz

||

Answers:

You can’t do such directly with dict[keyword]. You have to iterate through the dict and match each key against the keyword and return the corresponding value if the keyword is found.
This is going to be an O(N) operation.

>>> my_dict = {'name': 'Klauss', 'age': 26, 'Date of birth': '15th july'}
>>> next(v for k,v in my_dict.items() if 'Date' in k)
'15th july'

To get all such values use a list comprehension:

>>> [ v for k, v in my_dict.items() if 'Date' in k]
['15th july']

use str.startswith if you want only those values whose keys starts with ‘Date’:

>>> next( v for k, v in my_dict.items() if k.startswith('Date'))
'15th july'
>>> [ v for k, v in my_dict.items() if k.startswith('Date')]
['15th july']
Answered By: Ashwini Chaudhary

Sure it is possible:

print next(val for key, val in my_dict.iteritems() if key.startswith('Date'))

but this incurs a full scan through the dictionary. It only finds the first such matching key (where ‘first’ is arbitrary) and raises StopIteration instead of KeyError if no keys match.

To get closer to what you are thinking of, it’s better to write this as a function:

def value_by_key_prefix(d, partial):
    matches = [val for key, val in d.iteritems() if key.startswith(partial)]
    if not matches:
        raise KeyError(partial)
    if len(matches) > 1:
        raise ValueError('{} matches more than one key'.format(partial))
    return matches[0]
Answered By: Martijn Pieters

You are not suggesting a coherent API:

  1. What should be the result of my_dict['']? You don’t have a one-to-one mapping.
  2. How is it supposed to be extended to types other than str?

Another reason you can’t have it directly, even for strings and assuming you always return a list, is because Python’s dict is implemented using a hash table, and it will map xy and xz to unrelated cells in the table.

So, going the other way: such a lookup to would mean going for a slower implementation of dict, (which doesn’t make sense, optimizing for an uncommon use) or being as slower as a full scan – which you may as well write it by hand, as it is not that common to be worth a dedicated convenience method.

Answered By: Elazar

not the best solution, can be improved (overide getitem)

class mydict(dict):
    def __getitem__(self, value):
        keys = [k for k in self.keys() if value in k]
        key = keys[0] if keys else None
        return self.get(key)


my_dict = mydict({'name': 'Klauss', 'age': 26, 'Date of birth': '15th july'})
print(my_dict['Date'])# returns 15th july
Answered By: Ali SAID OMAR

There’s a nice and clever implementation of a ‘fuzzy’ dictionary in pywinauto – this might be perfect for what you need here.

https://code.google.com/p/pywinauto/source/browse/pywinauto/fuzzydict.py

and docs here:
http://pywinauto.googlecode.com/hg/pywinauto/docs/code/pywinauto.fuzzydict.html

(edit: although if you specifically want to match from the beginning of the key, you might need to replace SequenceMatcher logic with your custom code)

Answered By: formiaczek
>>> my_dict = {'name': 'Klauss', 'age': 26, 'Date of birth': '15th july'}
>>> next(v for k,v in my_dict.items() if 'Date' in k)
'15th july'


>>> [ v for k,v in my_dict.items() if 'Date' in k]
['15th july']


>>> next( v for k,v in my_dict.items() if k.startswith('Date'))
'15th july'
>>> [ v for k,v in my_dict.items() if k.startswith('Date')]
['15th july']

if i use the above given method i am getting StopIteration exception

Answered By: saurabh

You can use the built-in filter function to filter dictionaries, lists, etc. based on specific conditions.

filtered_dict = dict(filter(lambda item: "Date" in item[0], my_dict.items()))

The advantage is that you can use it for different data structures.

Answered By: Yogesh Kate
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.