Python: лучший способ писать вложенные циклы и операторы if

Я пытаюсь найти более питонический способ сделать следующее.

for employee in get_employees:
    for jobs in employee['jobs']:
        for nemployee in employee_comps:
            if nemployee['employee_id'] == employee['id']:
                for njob in nemployee['hourly_compensations']:
                    if njob['job_id'] == jobs['id']:
                        njob['rate'] = jobs['rate']

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

2 ответа

Решение

Основной комментарий, который я хотел бы сделать по поводу кода, заключается в том, что вы можете изменить порядок внешних трех for циклы, потому что выполняемая вами операция не зависит от порядка, в котором вы их перебираете (поскольку вы не выходите из каких-либо циклов при нахождении совпадения), и, учитывая, что это так, нет смысла делать то jobs петля только для достижения if заявление внутри него, которое не зависит от значения jobs. Было бы эффективнее поставитьjobs внутри двух других, так что он также может быть внутри if, т.е. цикл выполняется только для тех комбинаций значений employee а также nemployee где if состояние оценивает True.

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

from itertools import product

for employee, nemployee in product(get_employees, employee_comps):
    if nemployee['employee_id'] == employee['id']:
        for jobs, njob in product(employee['jobs'],
                                  nemployee['hourly_compensations']):
            if njob['job_id'] == jobs['id']:
                njob['rate'] = jobs['rate']

Ваш код очень чистый и питонический, я бы посоветовал ему остаться.

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

[[njob.update({njob['rate']: jobs['rate']}) for njob in nemployee['hourly_compensations'] if njob['job_id'] == jobs['id']] for employee in get_employees for jobs in employee['jobs'] for nemployee in employee_comps if nemployee['employee_id'] == employee['id']]
Другие вопросы по тегам