Подтвердить что ты не робот

Найдите индекс dict в списке, сопоставив значение dict

У меня есть список dicts:

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

Как я могу эффективно найти позицию индекса [0], [1] или [2] путем сопоставления имени name = 'Tom'?

Если бы это был одномерный список, я мог бы делать list.index(), но я не уверен, как продолжить поиск значений dicts в списке.

4b9b3361

Ответ 1

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'}

Ответ 2

Простая читаемая версия

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

Ответ 3

Это не будет эффективно, так как вам нужно пройти список, проверяющий каждый элемент в нем (O (n)). Если вы хотите повысить эффективность, вы можете использовать dict of dicts. На вопрос, вот один из возможных способов его найти (хотя, если вы хотите придерживаться этой структуры данных, на самом деле эффективнее использовать генератор, поскольку Брент Ньюей написал в комментариях, см. Также 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

Ответ 4

Здесь функция, которая находит позицию индекса словаря, если она существует.

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

Ответ 5

Кажется наиболее логичным использование компиляции filter/index:

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]

Ответ 6

Для данной итерируемой more_itertools.locate more_itertools.locate 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 среди других полезных инструментов.

Ответ 7

Один лайнер!?

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