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

时间:2010-12-08 20:00:36

标签: python

我有一个dicts列表:

list = [{'id':'1234','name':'Jason'},
        {'id':'2345','name':'Tom'},
        {'id':'3456','name':'Art'}]

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

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

11 个答案:

答案 0 :(得分:118)

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

如果需要从名称中重复获取,则应按名称(使用字典)对其进行索引,这样 get 操作将为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'}

答案 1 :(得分:37)

简单易读的版本是

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

答案 2 :(得分:9)

效率不高,因为您需要遍历列表检查其中的每个项目(O(n))。如果您想要效率,可以使用 dicts dict 。 关于这个问题,这里有一种可能的方法来找到它(但是,如果你想坚持这个数据结构,那么使用生成器实际上更有效,正如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

答案 3 :(得分:2)

这是一个找到字典索引位置的函数。

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

答案 4 :(得分:2)

@faham提供的答案很不错,但是它不会将索引返回包含该值的字典。而是返回字典本身。这是一种简单的获取方法:如果有多个索引,则一个或多个索引列表;如果不存在,则为空列表:

list = [{'id':'1234','name':'Jason'},
        {'id':'2345','name':'Tom'},
        {'id':'3456','name':'Art'}]

[i for i, d in enumerate(list) if 'Tom' in d.values()]

输出:

>>> [1]

我喜欢这种方法的地方是,通过简单的编辑,您既可以将索引又将字典作为元组得到一个列表。这是我需要解决并找到这些答案的问题。在下面的代码中,我在另一个字典中添加了重复的值以显示其工作原理:

list = [{'id':'1234','name':'Jason'},
        {'id':'2345','name':'Tom'},
        {'id':'3456','name':'Art'},
        {'id':'4567','name':'Tom'}]

[(i, d) for i, d in enumerate(list) if 'Tom' in d.values()]

输出:

>>> [(1, {'id': '2345', 'name': 'Tom'}), (3, {'id': '4567', 'name': 'Tom'})]

此解决方案可找到所有值中包含“ Tom”的所有字典。

答案 5 :(得分:2)

我需要一个更通用的解决方案来解决列表中多个字典具有键值的可能性,以及使用列表理解的简单实现:

dict_indices = [i for i, d in enumerate(dict_list) if d[dict_key] == key_value] 

答案 6 :(得分:1)

使用过滤器/索引组合似乎最符合逻辑:

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]

答案 7 :(得分:1)

对于给定的iterable,more_itertools.locate产生满足谓词的项的位置。

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])

    // support lib
    compile "com.android.support:appcompat-v7:$supportlib_version"

    // kotlin
    compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"

    // ...

    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    testCompile 'junit:junit:4.12'
}

more_itertools是第三方库,可在其他有用工具中实施itertools recipes

答案 8 :(得分:1)

以下将返回第一个匹配项的索引:

['Tom' in i['name'] for i in list].index(True)

答案 9 :(得分:0)

一个班轮!?

elm = ([i for i in mylist if i['name'] == 'Tom'] or [None])[0]

答案 10 :(得分:0)

def search(itemID,list):
     return[i for i in list if i.itemID==itemID]