Skip to content Skip to sidebar Skip to footer

Nested For Loops To List Comprehension With Differents "if" Conditions

I'm trying to convert this nested loop into a list comprehension but i'm not sure it's possible as there is different values possible for item in 'tmp' list. Is it the best way to

Solution 1:

nested comprehensions are not very readable

a simple

[something for something in container if something > 9]

is awesome, but a nested one is often confusing

you can simply move the loops into a generator function - it will still be readable and allow for lazy iteration

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()]

EDIT: just an opinionated addendum - this way the complicated nested loop can be named ( I named it no_idea_what_this_represents for obvious reasons ) but when a programmer sees

possible_views = [matrix for matrix in camera_matrices()]

he immediately knows what that means while something like

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

makes the programmer read a lot of lines and it is not obvious what is going on


Solution 2:

This can be done in one expression although I'm not sure readability is improved:

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)
]

Note that I've assumed you want to go through the whole of raw_x and raw_y rather than exactly 100 elements every time: the question implies 100-every-time but if the intention is really to go through the whole sequence, then it's better not to hard-code the 100 in there. If I'm wrong about the intention, you can change that inner-comprehension for loop to for i in range(100) and use raw_x[i] and raw_y[i] in the conditional expression instead of x and y.


Solution 3:

Your algorithm has large time complexity. First see if this is actually what you require. Once you are sure you need a nested for loop with 4 nesting levels, you can define a function to use within your list comprehension.

In this case, notice built-in map can accept multiple iterable arguments. functools.partial allows you to define functions with pre-set arguments.

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)]

Post a Comment for "Nested For Loops To List Comprehension With Differents "if" Conditions"