通过匹配dict的值来查找列表中dict的索引

ens*_*are 119 python

我有一个dicts列表:

list = [{'id':'1234','name':'Jason'},
        {'id':'2345','name':'Tom'},
        {'id':'3456','name':'Art'}]
Run Code Online (Sandbox Code Playgroud)

如何通过匹配name ='Tom'来有效地找到索引位置[0],[1]或[2]?

如果这是一维列表我可以做list.index()但我不知道如何继续搜索列表中的dicts的值.

tok*_*and 131

tom_index = next((index for (index, d) in enumerate(lst) if d["name"] == "Tom"), None)
# 1
Run Code Online (Sandbox Code Playgroud)

如果你需要从名称中重复获取,你应该按名称索引它们(使用字典),这样获取操作将是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.get("Tom")
# {'index': 1, 'id': '2345', 'name': 'Tom'}
Run Code Online (Sandbox Code Playgroud)

  • 恕我直言,这不是可读性,或者Pythonic是@Emile的答案。因为实际上并不是要创建一个生成器(对此我似乎很奇怪,所以要使用`next()`),所以目的只是获得索引。同样,这会引发StopIteration,而Python的lst.index()方法会引发ValueError。 (2认同)
  • @avoliva在下一个附近添加一个括号,如下面的那样((枚举(lst)中的(index,d)索引,如果d ["name"] =="Tom"),None) (2认同)

Emi*_*ile 40

简单易读的版本是

def find(lst, key, value):
    for i, dic in enumerate(lst):
        if dic[key] == value:
            return i
    return -1
Run Code Online (Sandbox Code Playgroud)

  • 这似乎是最可读和Pythonic.它也很好地模仿了`str.find()`的行为.您也可以将其称为`index()`并引发`ValueError`而不是返回-1,如果这是更可取的. (8认同)
  • 同意 - 当没有找到匹配时返回-1,你将总是得到列表中的最后一个字典,这可能不是你想要的.最好返回None并检查调用代码中匹配的存在性. (6认同)

aet*_*ter 9

它不会有效,因为您需要遍历列表检查其中的每个项目(O(n)).如果你想要效率,你可以使用dicts的dict.关于这个问题,这里有一种可能的方法来找到它(但是,如果你想坚持这个数据结构,使用生成器实际上更有效,正如Brent Newey在评论中写的那样;另见tokland的回答):

>>> L = [{'id':'1234','name':'Jason'},
...         {'id':'2345','name':'Tom'},
...         {'id':'3456','name':'Art'}]
>>> [i for i,_ in enumerate(L) if _['name'] == 'Tom'][0]
1
Run Code Online (Sandbox Code Playgroud)

  • @Brent Newey:生成器没有改变这个事实,你必须遍历整个列表,使搜索O(n)成为声明...根据列表的长度,使用生成器与使用之间的区别一个for循环或任何可能可以忽略不计的东西,使用dict与使用列表之间的区别可能不同 (2认同)