Самый pythoni c для выбора одной записи из списка dict на основе ключа dict? - PullRequest
2 голосов
/ 08 июля 2020

Допустим, у меня есть AllData, список вложенных dicts (давайте представим, что есть тысячи записей), но я ищу только одну запись.

AllData = [
    { "EntryA" : {"A Key":"A Value"} },
    { "EntryB" : {"B Key":"B Value"} },
    { "EntryC" : {"C Key":"C Value"} }
]

В настоящее время я просто зацикливаю через него и ломаюсь, как только найду соответствующий ключ.

MyKey = "EntryB"
FoundData = {}
for item in AllData:
    for key,data in item.items():
        if MyKey.lower() == key.lower():
            FoundData = data
            break
print(FoundData)

Однако, будучи энтузиастом Python, я знаю, что есть более элегантный способ сделать это. Я немного боролся с правильными методами понимания списка, но я пытаюсь! Ниже представлено лучшее, что я смог придумать, собирая эти данные в одну строку, но мне интересно, есть ли еще более элегантное решение этой проблемы.

MyKey = "EntryB"    
FoundData = [x for x in AllData if str(list(x.items())[0][0]).lower() == MyKey.lower()][0][MyKey]
print(FoundData)

Любое понимание буду очень признателен :)

Ответы [ 3 ]

3 голосов
/ 08 июля 2020

Если вы используете Python 3.8+, вы можете комбинировать выражение присваивания (:=) и any() (any() сломается, когда вы найдете первый действительный элемент):

AllData = [
    { "EntryA" : {"A Key":"A Value"} },
    { "EntryB" : {"B Key":"B Value"} },
    { "EntryC" : {"C Key":"C Value"} }
]

if any((found:=d) for d in AllData if "EntryB" in d):
    print(found)

Печать:

{'EntryB': {'B Key': 'B Value'}}
1 голос
/ 08 июля 2020

Я не думаю, что понимание списка является подходящим способом сделать это, поскольку вам нужно только первое совпадение.

all_data = [
    {"EntryA": {"A Key": "A Value"}},
    {"EntryB": {"B Key": "B Value"}},
    {"EntryC": {"C Key": "C Value"}}
]

targ_key = "EntryB"

found_data = None

for curr_dict in all_data:
    if found_data := curr_dict.get(targ_key):
        break

print(found_data)

Я все еще не совсем уверен, используется ли здесь выражение присваивания стоит, это может затруднить понимание.

Вот версия без выражения присваивания:

all_data = [
    {"EntryA": {"A Key": "A Value"}},
    {"EntryB": {"B Key": "B Value"}},
    {"EntryC": {"C Key": "C Value"}}
]

targ_key = "EntryB"

found_data = None

for curr_dict in all_data:
    curr_data = curr_dict.get(targ_key)
    if curr_data is not None:
        found_data = curr_data
        break

print(found_data)
0 голосов
/ 08 июля 2020

Вы можете использовать filter(), в зависимости от содержимого MyKey, это будет выглядеть примерно так:

AllData = [
    { "EntryA" : {"A Key":"A Value"} },
    { "EntryB" : {"B Key":"B Value"} },
    { "EntryC" : {"C Key":"C Value"} }
]
MyKey = "EntryB"
found = list(filter(lambda x: MyKey in x.keys(), AllData))[0][MyKey]
print(found)
...