Python фильтрует список dict, чтобы вернуть один dict

У меня есть список dict, и мне нужно отфильтровать ключ «name» (значения гарантированно уникальны) во вложенном dict, чтобы вернуть один dict. У меня есть рабочее решение, но я подумал, что будут более эффективные / элегантные / питонические методы.

Я пробовал понимать словарь, но не мог понять, как он будет перебирать список

Решения для 2.7+ и 3 будут оценены.

companies=[
    {
        'c01': {
            'name':'x',
            'address': '1 st'
        }
    },
    {
        'c02': {
            'name':'y',
            'address': '2 st'
        }
    },
]

company = [ c for c in companies if c.values() == [ v for v in c.values() if v['name']=='x'] ][0]

print company

Выход:

{'c01': {'name': 'x', 'address': '1 st'}}

В ваших данных выборки нет 'loans'; на что именно вы надеетесь, что ваш код будет делать?

tripleee 31.10.2018 06:39

пожалуйста, поясните подробнее, что вы хотите получить. также выражение company = x == y принимает только истинное или ложное значение, но не любое другое значение.

Glyphack 31.10.2018 06:44

Я предполагаю, что OP вставил только часть списка и, следовательно, зафиксировал индекс с помощью loans. Если это не так, приведенный выше код завершится ошибкой индексации.

LeKhan9 31.10.2018 06:50
Вздох мои неудачные попытки маскировки
80chew 31.10.2018 07:02
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
4
134
5

Ответы 5

Что-то вроде этого. Циклы For можно улучшить, хотя

company_dict = {}
for company in companies:
    for c in company:
        company_dict[c] = company.get(c)


print (company_dict)

Мне всегда нравилось делать вещи более читабельными, чем пытаться играть в кодовый гольф - - хотя иногда бывает и весело :)

При этом мы можем просто перебирать каждый элемент в ваших компаниях и искать целевое имя, а затем возвращать информацию об этой компании:

def get_target_company_info(companies):
    TARGET_NAME = 'loans'
    for company in companies:
        company_id = company.keys()[0]
        name_val = company.get(company_id).get('name')

        if name_val == TARGET_NAME:
            return company

    return None

company = get_target_company_info(companies)

print company

выход:

{'c01': {'name': 'loans', 'address': '1 st'}}

Чтобы быть немного ближе к тому, что вы хотели, мы можем предоставить метод фильтрации и фильтр как таковой:

метод:

TARGET_NAME = 'loans'
def is_relevant_company(company):
    company_id = company.keys()[0]
    name_val = company.get(company_id).get('name')

    return company if name_val == TARGET_NAME else None

фильтр:

relevant_companies = filter(None, [is_relevant_company(company) for company in companies])

выход:

[{'c01': {'name': 'loans', 'address': '1 st'}}]

Попробуй это:

[c for c in companies if any(['name' in c[x] and c[x]['name']=='x' for x in c])]

это отфильтровывает все компании с name == "x", и вывод для вашего примера будет:

[
    {'c01': {'name': 'x', 'address': '1 st'}}
]

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

target = 'loans'
result = {}
for company in companies:
    data = company.values()[0]  # There is only one name & address per company record.
    if data['name'] == target:  # Check if the company name matches the target.
        result = data           # If so, set the result to the data for the target company.
        break                   # Then break from the loop, as you've found the only match.

Для python 3 вам необходимо внести следующие изменения:

data = list(company.values())[0]
def find_company_with_name(name):
    return next(c for c in companies if c.values()[0]['name'] == name)

Использование выражения генератора более эффективно, чем понимание списка, поскольку оно может прекратить поиск, как только найдет совпадение, без создания остальной части списка.

Другие вопросы по теме