Reputation: 731
I'm running into the problem of accumulating an array with a for-loop (my array is called condition_list
, and each row stores a unique configuration of parameters).
The code below is what I'm imagining for building this array:
param1_vals = [1.0f0 2.0f0 3.0f0]; # specific values here don't matter
param2_vals = [1.0f0 2.0f0 3.0f0]; # specific values here don't matter
param3_vals = [1.0f0 2.0f0 3.0f0]; # specific values here don't matter
condition_list = zeros(Float32, 1, 3) # initialize condition_list
for ii = 1:length(param1_vals)
for jj = 1:length(param2_vals)
for kk = 1:length(param3_vals)
row_to_stack = [param1_vals[ii], param2_vals[jj], param3_vals[kk])
condition_list = vcat(condition_list, row_to_stack)
end
end
end
condition_list = condition_list[2:end,:] # pop off that first row (leftover of the initialization)
So each row of the resulting condition_list
should have a unique configuration of each of the values of param1_vals
, param2_vals
, and param3_vals
.
The issue I'm running into is about scope of local variables -- I get a condition_list is not defined
error at the inner most line of the loop, when using vcat
. What's the most Julian way to approach this problem, if I can't use an array accumulation? Or perhaps there's some solution using push!
or something?
Also, is there a way you can accumulate an array without doing the stupid 'pop off the first row 'thing I did at the end? Can you start with a zero-row, 3 column array and accumulate rows onto it?
Upvotes: 2
Views: 1081
Reputation: 69869
A first comment is that maybe it is enough for you to have a lazy iterator of tuples. In this case it is enough if you write:
res = Iterators.product(param1_vals, param2_vals, param3_vals)
However, if you really need a matrix then run the following code on res
:
mapreduce(x -> hcat(x...), vcat, res)
Now if you really wanted to work with something that you do in your code I would go with:
condition_vec = Matrix{Float32}[]
for ii = 1:length(param1_vals)
for jj = 1:length(param2_vals)
for kk = 1:length(param3_vals)
row_to_stack = [param1_vals[ii] param2_vals[jj] param3_vals[kk]]
push!(condition_vec, row_to_stack)
end
end
end
condition_list = reduce(vcat, condition_vec)
However, this code is a bit over-complicated as you could simply do:
condition_vec = Matrix{Float32}[]
for p1 = param1_vals, p2 = param2_vals, p3 = param3_vals
push!(condition_vec, [p1 p2 p3])
end
condition_list = reduce(vcat, condition_vec)
without intermediate indexing.
Finally your code is not working as condition_list
is a global variable and you would have to write:
global condition_list = vcat(condition_list, row_to_stack)
to make it work (note that there is a change coming to Julia and soon this will not be needed; this comment is for current 1.4.2 release of Julia, or other releases post 1.0 release).
Finally note that:
row_to_stack = [param1_vals[ii], param2_vals[jj], param3_vals[kk])
is an incorrect syntax (you used )
not ]
at the end of the line).
Also you use ,
not just spaces as in my code to separate values which would create you a column vector (not a matrix with 1-row as this is I guess what you wanted from your use of zeros
function).
If you would have more questions regarding this code please ask in the comment.
Upvotes: 3