通过匹配字典的值来查找列表中字典的索引
我有一个列表:
list = [{'id':'1234','name':'Jason'}, {'id':'2345','name':'Tom'}, {'id':'3456','name':'Art'}]
如何通过匹配name ='Tom'来有效地find索引位置[0],[1]或[2]?
如果这是一个一维列表,我可以做list.index(),但我不知道如何继续search列表中的字典的值。
tom_index = next(index for (index, d) in enumerate(lst) if d["name"] == "Tom") # 1
正如其他人所指出的那样,如果你要从名字中重复获取,你最好用名字作为关键字来构造一个字典,所以得到的操作是O(1)。 只是一个想法:
def build_dict(seq, key): return dict((d[key], dict(d, index=index)) for (index, d) in enumerate(seq)) info_by_name = build_dict(lst, key="name") tom_info = info_by_name["Tom"] # {'index': 1, 'id': '2345', 'name': 'Tom'}
一个简单的可读版本是
def find(lst, key, value): for i, dic in enumerate(lst): if dic[key] == value: return i return -1
这将不是有效的,因为你需要走检查列表中的每个项目(O(n))。 如果你想效率,你可以使用字典的字典 。 在这个问题上,下面是find它的一种可能的方法(不过,如果你想坚持这个数据结构, 使用一个生成器实际上更有效率,就像Brent Newey在评论中写的一样;另见托克兰的回答):
>>> L = [{'id':'1234','name':'Jason'}, ... {'id':'2345','name':'Tom'}, ... {'id':'3456','name':'Art'}] >>> [i for i,_ in enumerate(L) if _['name'] == 'Tom'][0] 1
这是一个函数,用于查找字典的索引位置(如果存在)。
dicts = [{'id':'1234','name':'Jason'}, {'id':'2345','name':'Tom'}, {'id':'3456','name':'Art'}] def find_index(dicts, key, value): class Null: pass for i, d in enumerate(dicts): if d.get(key, Null) == value: return i else: raise ValueError('no dict with the key and value combination found') print find_index(dicts, 'name', 'Tom') # 1 find_index(dicts, 'name', 'Ensnare') # ValueError: no dict with the key and value combination found
看来最合理的使用filter/索引组合:
names=[{}, {'name': 'Tom'},{'name': 'Tony'}] names.index(filter(lambda n: n.get('name') == 'Tom', names)[0]) 1
如果你认为可能有多个匹配:
[names.index(n) for item in filter(lambda n: n.get('name') == 'Tom', names)] [1]
对于给定的迭代, more_itertools.locate
产生满足谓词的项目的位置。
import more_itertools as mit iterable = [ {"id": "1234", "name": "Jason"}, {"id": "2345", "name": "Tom"}, {"id": "3456", "name": "Art"} ] list(mit.locate(iterable, pred=lambda d: d["name"] == "Tom")) # [1]
more_itertools
是一个第三方库,实现itertools食谱之间的其他有用的工具。