Python: Change Order of Lists for Nested Loops

Advertisements

I am trying to write a code to change the order of called lists in nested loops.

The code I’m currently using is below. This is a simplified example so I have removed all the extra functions and documentation, the real code is for creating plots based on the attribute set by variable loop_by.
This code works, but is very long and has a lot of copy/paste code. Is there a better/pythonic way of doing this?

It is important to note, names must be of the format {color}_{shape}_{size}_{number} due to the names of the data files.
I have tried using the product from itertools in the logic block, but the name format is incorrect.

I’m sorry, this is my first question post and I’ve been teaching myself python (still learning pep8).
Thank you in advance.

CODE:

# Initial lists
colors = ['Red', 'Orange', 'Yellow', 'Green', 'Blue']
shapes = ['Circle', 'Triangle', 'Square', 'Rectangle']
sizes = ['small', 'medium', 'large']
numbers = [i for i in range(7)] #could be any number


# Which loop I am trying to use
loop_by = 'color'
    #loop_by = 'shape'
    #loop_by = 'size'
    #loop_by = 'number'


# Loop functions
def by_color():
    for shape in shapes:
        for size in sizes:
            for number in numbers:
                print('---')
                #call to other functions for more calculations
                for color in colors:
                    name = f'{color}_{shape}_{size}_{number}'
                    print(name)
                    #call to other functions for more calculations


def by_shape():
    for color in colors:
        for size in sizes:
            for number in numbers:
                print('---')
                #call to other functions for more calculations
                for shape in shapes:
                    name = f'{color}_{shape}_{size}_{number}'
                    print(name)
                    #call to other functions for more calculations


def by_size():
    for color in colors:
        for shape in shapes:
            for number in numbers:
                print('---')
                #call to other functions for more calculations
                for size in sizes:
                    name = f'{color}_{shape}_{size}_{number}'
                    print(name)
                    #call to other functions for more calculations


def by_number():
    for color in colors:
        for shape in shapes:
            for size in sizes:
                print('---')
                #call to other functions for more calculations
                for number in numbers:
                    name = f'{color}_{shape}_{size}_{number}'
                    print(name)
                    #call to other functions for more calculations


# Logic block to choose loop
if loop_by == 'color':
    by_color()
elif loop_by == 'shape':
    by_shape()
elif loop_by == 'size':
    by_size()
elif loop_by == 'number':
    by_number()
else:
    print('This loop is not possible')

>Solution :

I would clean it up by extracting out some methods, and using comprehensions, like this

def create_output(loop_by, colors, shapes, sizes, numbers):
    def parse(color, shape, size, number):
        match loop_by:
            case 'color':
                return f'{color}_{shape}_{size}_{number}'
            case 'shape':
                return f'{shape}_{color}_{size}_{number}'
            case 'size':
                return f'{size}_{color}_{shape}_{number}'
            case 'number':
                return f'{number}_{color}_{shape}_{size}'
            case _:
                raise ValueError()

    return [
        parse(c, s, z, n)
        for c in colors
        for s in shapes
        for z in sizes
        for n in numbers
    ]


if __name__ == '__main__':
    output = create_output(
        loop_by="color",
        colors=['Red', 'Orange', 'Yellow', 'Green', 'Blue'],
        shapes=['Circle', 'Triangle', 'Square', 'Rectangle'],
        sizes=['small', 'medium', 'large'],
        numbers=(range(7))
    )
    
    [print(x) for x in output]

Leave a ReplyCancel reply