Python список словарей поиска - PullRequest
336 голосов
/ 28 декабря 2011

Предположим, у меня есть это:

[
{"name": "Tom", "age": 10},
{"name": "Mark", "age": 5},
{"name": "Pam", "age": 7}
]

и с помощью поиска "Pam" в качестве имени я хочу получить соответствующий словарь: {name: "Pam", age: 7}

Как этого добиться?

Ответы [ 18 ]

4 голосов
/ 28 декабря 2011

Моей первой мыслью было бы, что вы, возможно, захотите создать словарь этих словарей ... если, например, вы собираетесь искать его более чем несколько раз.

Однако это может быть преждевременной оптимизацией. Что было бы не так с:

def get_records(key, store=dict()):
    '''Return a list of all records containing name==key from our store
    '''
    assert key is not None
    return [d for d in store if d['name']==key]
4 голосов
/ 28 декабря 2011
dicts=[
{"name": "Tom", "age": 10},
{"name": "Mark", "age": 5},
{"name": "Pam", "age": 7}
]

from collections import defaultdict
dicts_by_name=defaultdict(list)
for d in dicts:
    dicts_by_name[d['name']]=d

print dicts_by_name['Tom']

#output
#>>>
#{'age': 10, 'name': 'Tom'}
1 голос
/ 15 апреля 2019

Я думаю, что вы можете использовать Pandas, чтобы справиться с этим.

import pandas as pd

person_list = [
    {"name": "Tom", "age": 10},
    {"name": "Mark", "age": 5},
    {"name": "Pam", "age": 7}
]

person_df = pd.DataFrame(person_list)
person_df[person_df["name"] == "Pam"].to_dict('records')

Он выводит:

[{'age': 7, 'name': 'Pam'}]

Преимущества:

  • Предоставление пандвысокопроизводительная обработка данных, что означает, что если у вас большой набор данных, поиск не займет много времени.
  • Структура данных проста в использовании, и вы можете обрабатывать свои данные как таблицу для дальнейшего анализа.
1 голос
/ 03 декабря 2018

Вы можете попробовать это:

''' lst: list of dictionaries '''
lst = [{"name": "Tom", "age": 10}, {"name": "Mark", "age": 5}, {"name": "Pam", "age": 7}]

search = raw_input("What name: ") #Input name that needs to be searched (say 'Pam')

print [ lst[i] for i in range(len(lst)) if(lst[i]["name"]==search) ][0] #Output
>>> {'age': 7, 'name': 'Pam'} 
1 голос
/ 13 августа 2018

Простое использование списка:

[i for i in dct if i['name'] == 'Pam'][0]

Пример кода:

dct = [
    {'name': 'Tom', 'age': 10},
    {'name': 'Mark', 'age': 5},
    {'name': 'Pam', 'age': 7}
]

print([i for i in dct if i['name'] == 'Pam'][0])

> {'age': 7, 'name': 'Pam'}
0 голосов
/ 18 января 2018

Я нашел эту тему, когда искал ответ на тот же вопрос. Хотя я понимаю, что это поздний ответ, я думал, что внесите его, если он кому-нибудь пригодится:

def find_dict_in_list(dicts, default=None, **kwargs):
    """Find first matching :obj:`dict` in :obj:`list`.

    :param list dicts: List of dictionaries.
    :param dict default: Optional. Default dictionary to return.
        Defaults to `None`.
    :param **kwargs: `key=value` pairs to match in :obj:`dict`.

    :returns: First matching :obj:`dict` from `dicts`.
    :rtype: dict

    """

    rval = default
    for d in dicts:
        is_found = False

        # Search for keys in dict.
        for k, v in kwargs.items():
            if d.get(k, None) == v:
                is_found = True

            else:
                is_found = False
                break

        if is_found:
            rval = d
            break

    return rval


if __name__ == '__main__':
    # Tests
    dicts = []
    keys = 'spam eggs shrubbery knight'.split()

    start = 0
    for _ in range(4):
        dct = {k: v for k, v in zip(keys, range(start, start+4))}
        dicts.append(dct)
        start += 4

    # Find each dict based on 'spam' key only.  
    for x in range(len(dicts)):
        spam = x*4
        assert find_dict_in_list(dicts, spam=spam) == dicts[x]

    # Find each dict based on 'spam' and 'shrubbery' keys.
    for x in range(len(dicts)):
        spam = x*4
        assert find_dict_in_list(dicts, spam=spam, shrubbery=spam+2) == dicts[x]

    # Search for one correct key, one incorrect key:
    for x in range(len(dicts)):
        spam = x*4
        assert find_dict_in_list(dicts, spam=spam, shrubbery=spam+1) is None

    # Search for non-existent dict.
    for x in range(len(dicts)):
        spam = x+100
        assert find_dict_in_list(dicts, spam=spam) is None
0 голосов
/ 16 января 2016

Вот сравнение с использованием итерации по списку, с использованием фильтра + лямбда или рефакторингом (если необходимо или допустимо для вашего случая) вашего кода, чтобы диктовать, а не список диктов

import time

# Build list of dicts
list_of_dicts = list()
for i in range(100000):
    list_of_dicts.append({'id': i, 'name': 'Tom'})

# Build dict of dicts
dict_of_dicts = dict()
for i in range(100000):
    dict_of_dicts[i] = {'name': 'Tom'}


# Find the one with ID of 99

# 1. iterate through the list
lod_ts = time.time()
for elem in list_of_dicts:
    if elem['id'] == 99999:
        break
lod_tf = time.time()
lod_td = lod_tf - lod_ts

# 2. Use filter
f_ts = time.time()
x = filter(lambda k: k['id'] == 99999, list_of_dicts)
f_tf = time.time()
f_td = f_tf- f_ts

# 3. find it in dict of dicts
dod_ts = time.time()
x = dict_of_dicts[99999]
dod_tf = time.time()
dod_td = dod_tf - dod_ts


print 'List of Dictionries took: %s' % lod_td
print 'Using filter took: %s' % f_td
print 'Dict of Dicts took: %s' % dod_td

И выводэто:

List of Dictionries took: 0.0099310874939
Using filter took: 0.0121960639954
Dict of Dicts took: 4.05311584473e-06

Вывод: Очевидно, что наличие словаря словесных слов является наиболее эффективным способом поиска в тех случаях, когда, как вы знаете, вы будете искать по идентификаторамтолько.интересно использовать фильтр - самое медленное решение.

0 голосов
/ 28 декабря 2011

Вы должны пройти через все элементы списка.Это не ярлык!

Если где-то еще вы не ведете словарь имен, указывающих на элементы списка, но тогда вам нужно позаботиться о последствиях выталкивания элемента из вашего списка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...