Reputation: 605
I am designing a program in which I'm trying to avoid nesting conditional statements.
Basically, I have 2 sets of 3 parameters : a_changes
, b_changes
and c_changes
are bools,
and they are associated with a
, b
and c
, that are lists if they change or floats if they don't.
My aim is to transform non-changing parameters into lists of the same length as changing parameters.
An example would be :
a_changes = True
b_changes = False
c_changes = False
a = [0.21, 0.25, 0.29]
b = 0.13
c = 0.78
becomes
a_changes = True
b_changes = False
c_changes = False
a = [0.21, 0.25, 0.29]
b = [0.13, 0.13, 0.13]
c = [0.78, 0.78, 0.78]
Problem is : multiple parameters can change at the same time, so you could have :
a_changes = True
b_changes = True
c_changes = False
a = [0.21, 0.25, 0.29]
b = [0.13, 0.13, 0.13]
c = 0.78
becomes
a_changes = True
b_changes = True
c_changes = False
a = [0.21, 0.25, 0.29]
b = [0.13, 0.13, 0.13]
c = [0.78, 0.78, 0.78]
If multiple parameters change, their length is the same, so no problem coming from there. However, I would want to avoid having a multitude of nested conditional statements. Is it at all possible? Is there a Data Structure I could use?
Upvotes: 1
Views: 108
Reputation: 114330
You have a lot of redundant information it seems. The processing really only depends on whether something is a list: booleans are not necessary. Also, you don't need separate variables, since it's easier to work with batches of things when they are in a sequence.
Store your data in a list:
data = [a, b, c]
Get the length of a list:
size = next((len(x) for x in data if isinstance(x, list)), 1)
Notice that this call to next
guards against all the elements being float
by returning one. Now do the transform:
for i in range(len(data)):
if ~isinstance(data[i], list):
data[i] = [data[i]] * size
Or more concisely:
data = [x if isinstance(x, list) else [x] * size for x in data]
Upvotes: 1
Reputation: 51653
This should work if at least one input is a list:
def refine_arguments(a, b, c, a_changes, b_changes, c_changes):
# get the max len of one of the list (should be all the same listlenght)
maxlen = max(len(i) for i in (a, b, c) if isinstance(i, list))
# if the X_changes is true use the float value times maxlen, else leave as is
a = [a] * maxlen if not a_changes and not isinstance(a, list) else a
b = [b] * maxlen if not b_changes and not isinstance(b, list) else b
c = [c] * maxlen if not c_changes and not isinstance(c, list) else c
return a, b, c
a_changes = True
b_changes = True
c_changes = False
a = [0.21, 0.25, 0.29]
b = [0.13, 0.13, 0.13]
c = 0.78
print(*refine_arguments(a, b, c, a_changes, b_changes, c_changes))
a_changes = True
b_changes = False
c_changes = False
a = [0.21, 0.25, 0.29]
b = 0.78
c = 0.78
print(*refine_arguments(a, b, c, a_changes, b_changes, c_changes))
Output:
[0.21, 0.25, 0.29] [0.13, 0.13, 0.13] [0.78, 0.78, 0.78]
[0.21, 0.25, 0.29] [0.78, 0.78, 0.78] [0.78, 0.78, 0.78]
Use a,b,c = refine_arguments(a, b, c, a_changes, b_changes, c_changes)
to work with a,b,c later on.
Upvotes: 1
Reputation: 984
The data structure you may want to use are numpy arrays. If you have a lot of parameters, use a dictionary to allow loop operations:
my_data = {}
my_data["a"] = [0.21, 0.25, 0.29]
my_data["b"] = 0.13
my_data["c"] = 0.78
length = 1
for param in my_data:
my_data[param] = np.array(my_data[param], ndmin=1) # at least 1d
length = max(length, len(my_data[param]))
for param in my_data:
my_data[param] = np.ones(length) * my_data[param] # make sure all is the same lentgh
Upvotes: 1