Mikhail Tokarev Mikhail Tokarev - 1 month ago 5
Python Question

Python. Best way to match dictionary value if condition true

I'm trying to build a parser now part of my code is looks like this:

azeri_nums = {k:v for k,v in zip(range(1,10),("bir","iki","uc","dord","beş","altı","yeddi","səkkiz","doqquz"))}
russian_nums = {k:v for k,v in zip(range(1,10),("один","два","три","четыре","пять","шесть","семь","восемь","девять"))}


Imagine that I should find the digit if roomnum ="одна"
Here is how I trying to match this:

if roomnum.isalpha():
for key,value in azeri_nums.items():
if value.startswith(roomnum.lower()):
roomnum = str(key)
break

if roomnum.isalpha():
for key,value in russian_nums.items():
if value.startswith(roomnum.lower()):
roomnum = str(key)
break


is there any other method to do that that will work faster, or some best practices for this situation?

Thank you in advance!

P.S.
the reason that this code works that module "re" capture from "одна" only "од" and that is why "один".startswith("од") returns true.

Answer

Change your dict to be

azeri_nums = {v.lower():k for k,v in zip(range(1,10),("bir","iki","uc","dord","beş","altı","yeddi","səkkiz","doqquz"))}
russian_nums  = {v.lower():k for k,v in zip(range(1,10),("один","два","три","четыре","пять","шесть","семь","восемь","девять"))}

And once you've names mapped to digits, just use:

key = None # By default
roomnum_lower = roomnum.lower()
if roomnum_lower in azeri_nums:
    key = azeri_nums[roomnum_lower]
elif roomnum_lower in russian_nums:
    key = russian_nums[roomnum_lower]

Dictionary is based on keysearch, not valuesearch. The first one is O(1) and allows u to use key in dict when the 2nd one is O(n) and requires looping.

EDIT TO COMMENT:

if you want to map one word to others, create another dict that will handle it.

 string_map = {'одна': ['один',]} # map single string to many others if u want

And then all u need to do is:

key = None # By default
roomnum_lower = roomnum.lower()
if roomnum_lower in azeri_nums:
    key = azeri_nums[roomnum_lower]
elif roomnum_lower in russian_nums:
    key = russian_nums[roomnum_lower] 
if key is None:
    # At this point you know that the single string is not in any dict,
    # so u start to check if any other string that u assigned to it is in dict
    for optional_string in string_map.get(roomnum_lower, []):
        opt_str_low = optional_string.lower()
        key = azeri_nums.get(opt_str_low, None)
        key = russian_nums.get(opt_str_low, None) if key is None else key