вложенный в циклы для перечисления понимания с различными условиями "если" - PullRequest
0 голосов
/ 07 января 2019

Я пытаюсь преобразовать этот вложенный цикл в понимание списка, но я не уверен, что это возможно, поскольку для элемента в списке "tmp" возможны разные значения. Это лучший способ сделать это? Спасибо!

final = []
for a in range(-13, 1):
    for b in range(0,4):
        for c in range(6, 49):
            for d in range(48, 94):
                tmp = [0 for i in range(100)]
                for i in range(100):
                    if raw_x[i] >= b and raw_y[i] >= d:
                        tmp [i] = -1
                    if raw_x[i] <= a and raw_y[i] <= c:
                        tmp [i] = 1
                final.append(tmp)

Ответы [ 3 ]

0 голосов
/ 07 января 2019

Это можно сделать в одном выражении, хотя я не уверен, что читаемость улучшена:

final = [
    [
        +1 if x <= a and y <= c
        else -1 if x >= b and y >= d
        else 0
        for x, y in zip( raw_x, raw_y )
    ]
    for a in range(-13, 1)
    for b in range(0, 4)
    for c in range(6, 49)
    for d in range(48, 94)
]

Обратите внимание, что я предположил, что вы хотите пройти через целое из raw_x и raw_y, а не ровно 100 элементов каждый раз: вопрос подразумевает 100-каждый раз, но если намерение на самом деле, чтобы пройти всю последовательность, то лучше не кодировать 100 там. Если я ошибаюсь в намерении, вы можете изменить цикл for внутреннего понимания на for i in range(100) и использовать raw_x[i] и raw_y[i] в условном выражении вместо x и y.

0 голосов
/ 07 января 2019

вложенные понимания не очень читабельны

простой

[something for something in container if something > 9]

круто, но вложенный часто сбивает с толку

Вы можете просто переместить циклы в функцию генератора - она ​​будет по-прежнему читабельна и позволит выполнять ленивую итерацию

def no_idea_what_this_represents():
    for a in range(-13, 1):
        for b in range(0,4):
            for c in range(6, 49):
                for d in range(48, 94):
                    tmp = [0 for i in range(100)]
                    for i in range(100):
                        if raw_x[i] >= b and raw_y[i] >= d:
                            tmp [i] = -1
                        if raw_x[i] <= a and raw_y[i] <= c:
                            tmp [i] = 1
                    yield tmp

final = [signs for signs in no_idea_what_this_represents()]

РЕДАКТИРОВАТЬ: просто вымышленное приложение - так можно назвать сложный вложенный цикл (я назвал его no_idea_what_this_represents по понятным причинам), но когда программист видит

possible_views = [matrix for matrix in camera_matrices()]

он сразу знает, что это значит, в то время как что-то вроде

possible_views = [device.matrix 
                  for devices in itertools.chain(connected_devices(), buffered_devices()
                  for device in devices
                  if device.type=='camera']

заставляет программиста читать много строк, и неясно, что происходит

0 голосов
/ 07 января 2019

Ваш алгоритм имеет большую временную сложность. Сначала посмотрите, действительно ли это , что вам требуется. Если вы уверены, что вам нужен вложенный цикл for с 4 уровнями вложенности, вы можете определить функцию для использования в пределах вашего понимания списка.

В этом случае встроенное уведомление map может принимать несколько итерируемых аргументов. functools.partial позволяет определять функции с предустановленными аргументами.

from functools import partial

def get_val(x, y, a, b, c, d):
    if x <= a and y <= c:
        return 1
    if x >= b and y >= d:
        return -1
    return 0

final = [list(map(partial(get_val, a=a, b=b, c=c, d=d), raw_x, raw_y)) \
         for a in range(-13, 1) \
         for b in range(0, 4) \
         for c in range(6, 49) \
         for d in range(48, 94)]
...