How to change order of lists for nested loops
Question:
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')
Answers:
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]
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')
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]