Given a dictionary of lists
node_to_index = {"global": [0],
"l_eye": list(range(42, 48)),
"r_eye": list(range(36, 42)),
"l_brow": list(range(22, 27)),
"r_brow": list(range(17, 22)),
"mouth": list(range(48, 68)),
"nose": list(range(27, 35)),
}
Given a number eg 37, it would return index of the "r_eye" key which is 2
I'd go with a generator expression and enumerate
, with next
to shortcut as soon as the condition is satisfied:
next((ix for ix, (_,v) in enumerate(node_to_index.items()) if 37 in v), None)
# 2
Note that for python versions under 3.7, dictionaries' insertion order is not preserved. So you should consider using collections.OrderedDict
:
from collections import OrderedDict
node_to_index = OrderedDict({
"global": [0],
"l_eye": list(range(42, 48)),
"r_eye": list(range(36, 42)),
"l_brow": list(range(22, 27)),
"r_brow": list(range(17, 22)),
"mouth": list(range(48, 68)),
"nose": list(range(27, 35)),
})
next((ix for ix, (_,v) in enumerate(node_to_index.items()) if 37 in v), None)
# 2
You should use collections.OrderedDict
to guarantee its order(index).
from collections import OrderedDict
node_to_index = OrderedDict({
"global": [0],
"l_eye": list(range(42, 48)),
"r_eye": list(range(36, 42)),
"l_brow": list(range(22, 27)),
"r_brow": list(range(17, 22)),
"mouth": list(range(48, 68)),
"nose": list(range(27, 35)),
})
def find_index(target: int) -> int:
for idx, value in enumerate(node_to_index.values()):
if target in value:
return idx
return -1
print(find_index(37))
output:
2
If you are using CPython earlier than 3.6 or other interpreter earlier than 3.7, order of dict
isn't guaranteed at even creation. So do this:
node_to_index = OrderedDict([
('global', [0]),
('l_eye', list(range(42, 48))),
('r_eye', list(range(36, 42))),
('l_brow', list(range(22, 27))),
('r_brow', list(range(17, 22))),
('mouth', list(range(48, 68))),
('nose', list(range(27, 35))),
])
It is not quite relative OP's question, but appended for comments.
You have three options for absence of target value.
return -1
raise ValueError(f'{target} is not found')
return None
Note that if the function returns in some cases, omitting otherwise's return None
is not recommended by PEP8.
You just iterate through the items until 37 is in the list associated to that key.
Note that you have to handle edge cases like what to do if several lists contain the number (currently it's the first one that is returned) or if no list contains it (currently it returns None
).
def find_number(number, my_dict):
for n, (key, value) in enumerate(my_dict.items()):
if number in value:
return n
node_to_index = {"global": [0],
"l_eye": list(range(42, 48)),
"r_eye": list(range(36, 42)),
"l_brow": list(range(22, 27)),
"r_brow": list(range(17, 22)),
"mouth": list(range(48, 68)),
"nose": list(range(27, 35)),
}
find_number(37, node_to_index) # returns 2
node_to_index = {"global": [0],
"l_eye": list(range(42, 48)),
"r_eye": list(range(36, 42)),
"l_brow": list(range(22, 27)),
"r_brow": list(range(17, 22)),
"mouth": list(range(48, 68)),
"nose": list(range(27, 35)),
}
def get_key(val):
pos = 0
for key, value in node_to_index.items():
for elem in value:
if elem == val:
return pos
pos += 1
print(get_key(27))
If you are certain that the value is present in one of the lists, you could use the index() method on a list comprehension:
value = 37
index = [value in nodes for nodes in node_to_index.values()].index(True)
print(index) # 2
Note that using a dictionary for this is probably not the best choice. You seem to only need a list of tuples. This would make the index more reliable and meaningful:
node_to_index = [ ( "global", [0]),
( "l_eye", list(range(42, 48) ),
( "r_eye", list(range(36, 42) ),
( "l_brow", list(range(22, 27) ),
( "r_brow", list(range(17, 22) ),
( "mouth", list(range(48, 68) ),
( "nose", list(range(27, 35) )
]
value = 37
index = [value in nodes for _,nodes in node_to_index].index(True)
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.