0

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.

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')
3
  • See the dupe target for the general tools. Specific to your use case, you'll likely want to create a dict lookup of function that create the permutation iterators for each "loop-by" order. E.g. lookup = {"color": by_color, ...} with def by_color(): return itertools.permutations(shapes, sizes, numbers, colors) Commented Mar 2, 2023 at 20:14
  • "See the dupe target for the general tools." What do you mean? Commented Mar 2, 2023 at 20:51
  • It's in the blue box at the top of the question. Commented Mar 2, 2023 at 21:40

1 Answer 1

0

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]
Sign up to request clarification or add additional context in comments.

1 Comment

I will try a version of this, thank you for your response. Sadly I am limited to python 3.9.13 and cannot use match

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.