Оптимизируйте код с пониманием словаря

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

Как мне оптимизировать этот код правильным питоническим способом?

all_users = []
for x in range(len(result)):
    user = {}
    user["fieldy"] = str(result[x][1].get("valueforfield1", None))[3:-2]
    user["fieldx"] = str(result[x][1].get("valueforfield2", None))[3:-2]
    user["fieldc"] = str(result[x][1].get("valueforfield3", None))[3:-2]
    user["fieldv"] = str(result[x][1].get("valueforfield4", None))[3:-2]
    user["fieldb"] = str(result[x][1].get("valueforfield5", None))[3:-2]
    all_users.append(user)

пример значения результата

result = [('CN=Xxx X,OU=X,OU=X,DC=X,DC=X', {'valueforfield1': [b'Va'], 'valueforfield2': [b'val'], 'valueforfield3': [b'+123'], 'valueforfield4': [b'[email protected]'], 'valueforfield5': [b'examplevalue']}),('CN=Yyy Y,OU=Y,OU=Y,DC=Y,DC=Y', {'valueforfield1': [b'Ycx'], 'valueforfield2': [b'Dy'], 'valueforfield3': [b'+321'], 'valueforfield4': [b'[email protected]'], 'valueforfield5': [b'examplevaluey']})]

после выполнения кода словарь user имеет следующий контент после первой итерации цикла for

{"fieldy": "Va", "fieldx": "val", "fieldc": "+123", "fieldv": "[email protected]", "fieldb": "examplevalue"}

Также я должен написать функцию для замены кода user["field1"] = str(result[x][1].get("valueforfield1", None))[3:-2]? Стоит ли и рекомендуется ли? Спасибо!


person jv95    schedule 07.06.2019    source источник
comment
Что такое result?   -  person Devesh Kumar Singh    schedule 07.06.2019
comment
Вы не можете оптимизировать его с точки зрения скорости, только в том, чтобы сделать код более лаконичным.   -  person roganjosh    schedule 07.06.2019
comment
опубликуйте свое значение result   -  person RomanPerekhrest    schedule 07.06.2019
comment
извините, обновил.   -  person jv95    schedule 07.06.2019
comment
@ jv95, Хорошо, как ты определяешь, что fieldy соответствует valueforfield1? по каким критериям?   -  person RomanPerekhrest    schedule 07.06.2019
comment
по его имени. fieldy всегда будет принимать значение из valueforfield1. valueforfield1 — это имя ключа в словаре из result.   -  person jv95    schedule 07.06.2019
comment
Я имею в виду, вы сказали, что единственная статическая вещь в result — это клавиша вроде valueforfield1. Тогда как строится слово fieldy? Должна ли это быть завершающая часть ключа valueforfield1: после valuefor --> field1 ?   -  person RomanPerekhrest    schedule 07.06.2019
comment
fieldy — жестко заданное имя. Он не построен никаким кодом. Это имя, которое я дал ключу. Надеюсь, я правильно понял ваш вопрос.?   -  person jv95    schedule 07.06.2019
comment
Подтверждаете ли вы, что следующее {"fieldy": "valueforfield1", "fieldx": "valueforfield2", "fieldc": "valueforfield3", "fieldv": "valueforfield4", "fieldb": "valueforfield5", "fieldn": "valueforfield6", } является правильным сопоставлением для соответствия?   -  person RomanPerekhrest    schedule 07.06.2019
comment
Значение в ключе fieldy должно быть Va, fieldx должно быть Val и т. д. Обратите внимание, что KEY fieldy берет ЗНАЧЕНИЕ из dic, где KEY равно valueforfield1. надеюсь теперь понятно?   -  person jv95    schedule 07.06.2019
comment
это ваше подтверждение? Вы не видите конечные значения при планировании обработки, но вы должны заранее установить соответствие ключей   -  person RomanPerekhrest    schedule 07.06.2019
comment
Да, это мое подтверждение. Я задаю имя ключа fieldy, а затем добавляю к нему значение. Значение берется из ключа valueforfield1, который берется из result. valueforfield1 всегда будет в result .   -  person jv95    schedule 07.06.2019
comment
Хорошо, предоставлю решение через минуту.   -  person RomanPerekhrest    schedule 07.06.2019


Ответы (2)


При хорошо факторизованном подходе:

result = [('CN=Xxx X,OU=X,OU=X,DC=X,DC=X',
           {'valueforfield1': [b'Va'], 'valueforfield2': [b'val'], 'valueforfield3': [b'+123'],
            'valueforfield3': [b'[email protected]'], 'valueforfield5': [b'examplevalue']}),
          ('CN=Yyy Y,OU=Y,OU=Y,DC=Y,DC=Y',
           {'valueforfield1': [b'Ycx'], 'valueforfield2': [b'Dy'],
            'valueforfield3': [b'+321'], 'valueforfield3': [b'[email protected]'],
            'valueforfield5': [b'examplevaluey']})]

def compose_user_details(data):
    keys_map = {"fieldy": "valueforfield1", "fieldx": "valueforfield2",
                "fieldc": "valueforfield3", "fieldv": "valueforfield4",
                "fieldb": "valueforfield5", "fieldn": "valueforfield6",
                }
    user_details = []

    for i in range(len(result)):
        dataset = result[i][1]  # getting the needed `data source` at once
        user_details.append({k: str(dataset.get(v, None))[3:-2]
                             for k,v in keys_map.items()})
    return user_details

print(compose_user_details(result))

Выход:

[{'fieldy': 'Va', 'fieldx': 'val', 'fieldc': '[email protected]', 'fieldv': '', 'fieldb': 'examplevalue', 'fieldn': ''}, {'fieldy': 'Ycx', 'fieldx': 'Dy', 'fieldc': '[email protected]', 'fieldv': '', 'fieldb': 'examplevaluey', 'fieldn': ''}]
person RomanPerekhrest    schedule 07.06.2019
comment
@ jv95, пожалуйста. Вы можете удалить "fieldn": "valueforfield6" элемент из keys_map, если он не нужен. - person RomanPerekhrest; 07.06.2019

Используя только понимание dict, чтобы позаботиться о повторяющемся коде:

all_users = []
for x in range(len(result)):
    user = {f"field{i}": str(result[x][1].get(f"valueforfield{i}", None))[3:-2] for i in range(1, 7)}
    all_users.append(user)

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

all_users = [{
        f"field{i}": str(result[x][1].get(f"valueforfield{i}", None))[3:-2] 
        for i in range(1, 7)
    } for x in range(len(result))]

Трудность в приведенном вами примере связана с именами ключей, но, поскольку они являются обычными, я использовал строку формата, чтобы просто вставить целое число, которое ожидает ключ (то есть f"field{i}" разрешается в "field1" когда i = 1, "field2" когда i = 2, и так далее).


В общем, понимания на самом деле не оптимизируют скорость — они больше позволяют избежать повторного использования кода.

person Green Cloak Guy    schedule 07.06.2019
comment
Это действительно красивое решение. Но что бы вы сделали, если бы имена не были такими красивыми? У меня есть другая часть кода с той же проблемой, но имена такие.. fieldexample должен получить значение из valueforexamplefield и т. д. здесь я не могу использовать ваше поле1, когда я = 1, поле2, когда я = 2, как бы вы это решили ? Я не публиковал код, потому что думал, что смогу использовать решение для обоих циклов, которые у меня есть. - person jv95; 07.06.2019
comment
@ jv95, почему бы вам не опубликовать репрезентативную, тестируемую структуру ввода? - person RomanPerekhrest; 07.06.2019
comment
@ jv95 jv95, если вы хотите использовать понимание этих данных, вам нужно придумать систему, чтобы определить, какой ключ должен соответствовать какому значению. Вы можете, например, использовать жестко закодированный dict индекса для ключа и поместить его в строку формата - например. my_dict={1:'y', 2:'x', ...}, а затем f"field{my_dict[i]}". Или придумать какое-нибудь другое действенное решение этой проблемы. - person Green Cloak Guy; 07.06.2019
comment
Это невозможно, так как результат будет отличаться каждый раз, когда я запускаю код. По сути, вся идея заключается в том, чтобы создать словари в all_users и заполнить эти словари значениями из result . длина и значения result каждый раз будут разными. Единственная статическая вещь в результате - это имя ключа как valueforfield1 и т. д. - person jv95; 07.06.2019
comment
@jv95 stackoverflow.com/questions/56499932/ - person RomanPerekhrest; 07.06.2019