Reputation: 269
I want to get value from the dictionary by the part of the key, e.g. I have a dict
with a compound key
tr_dict = {'UTABI-OSGAN': {"properties": {"id": "789"}},
'ABOKA-OSGAN': {"properties": {"id": "111"}},
'FE-DERIG': {"properties": {"id": "243"}}}
and I want to get values with key started 'UTABI'
(the other case when key endswith e.g. 'DERIG'
)
I suppose it looks something like
start = 'UTABI'
tr_dict.get(start + '[-A-Z]{2,5}')
I know this syntax is incorrect but is it possible to do something like this?
Upvotes: 1
Views: 4616
Reputation: 77912
Short answer: no. Dicts are not SQL databases, you have to give the exact key.
The brute force solution is to loop over the dict's keys and use string methods to find the relevant ones, ie:
for key in tr_dict:
if key.startswith("UTABI-"):
print("found {} : {}".format(key, tr_dict[key]))
which of course is O(n) and kind of defeat the whole point of having dicts. This is ok if you only need to do this lookup once for a given tr_dict
, but sub-optimal if tr_dict
has a long lifetime and will be looked up more than once for a given "partial" key.
Another solution which requires more upfront processing but allow for O(1) access afterward is to preprocess the whole dict once to build a new one with keys you can lookup directly:
from collections import defaultdict
lookups = [
# (key: callback)
("UTABI", lambda k: k.startswith("UTABI-")),
("DERIG", lambda k: k.endswith("-DERIG")),
]
index = defaultdict(list)
for newkey, match in lookups:
for oldkey in tr_dict:
if match(oldkey):
index[newkey].append(tr_dict[oldkey])
This is overkill for a one-shot lookup, but much better if you have to lookup those keys more than once for a given tr_dict.
Upvotes: 3
Reputation: 3445
Here's one way of doing it,
return_values = {k:v for k,v in tr_dict.items() if k.startswith('UTABI') or k.endswith('DERIG')}
print(return_values)
Outputs:
{'UTABI-OSGAN': {'properties': {'id': '789'}}, 'FE-DERIG': {'properties': {'id': '243'}}}
And here's the expanded form, that does the same thing
return_values = []
for k,v in tr_dict.items():
if k.startswith('UTABI') or k.endswith('DERIG'): # Change your requirements here
return_values.append(v)
print(return_values)
Upvotes: 0
Reputation: 3713
The syntax you propose is interpreted as "give me the "UTABI[-A-Z]{2,5}" key".
As you want to filter "by intention" you can say :
filtered_dict = {key: value for key, value in tr_dict if key.startswith('UTABI')}
Upvotes: 0