for-loop over Structure Array
268 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
Hannes Stagge
el 11 de Feb. de 2020
Comentada: Stephen23
el 12 de Oct. de 2022
Hello together,
I am currently working with multiple experimental datasets containing velocitys of different fluid components and pressure losses. One of those datasets is contained in a structure with fields containing the experimental data as arrays.
My task ist to calculate the same dimensionless numbers for every dataset from the presure losses, densities, velocities, etc. I have written a loop over all structures grouped to an array, however calculations are only saved to the index (i) of the loop , not to the original structures in the array. So only the last calculation is saved. I suspect the calculations are running correctly inside the loop but don't get saved to the right output structure.
Code:
A=load('dataset1.mat'); %saved workspace with dataset1
B=load('dataset2.mat'); %saved workspace with dataset2
% and so on
A.vel1 %returns 15x1 double
A.vel2 %returns 15x1 double
B.vel1 %returns 24X1 double
B.vel2 %returns 24x1 double
A.rho=997; %additional data
B.rho=876;
%and so on
for i=[A,B]: %loop over all datasets
i.f1=i.rho*i.vel1;
%and so on
end
A.f %Error: Reference to non-existent field 'f'
B.f %Error: Reference to non-existent field 'f'
i.f %returns 24x1 double with right values B.rho*B.vel1
Can anybody exlpain to me, why this happens and how I can fix it, so that all calculations are computed and saved in A and B?
Thank you for your help!
1 comentario
Respuesta aceptada
Stephen23
el 11 de Feb. de 2020
Editada: Stephen23
el 11 de Feb. de 2020
"Can anybody exlpain to me, why this happens"
Because MATLAB is (as far the end-user is concerned) pass-by-value and not pass-by-reference as you are trying to use it. So when you change the structures in the loop you change the ones in the loop only... but this is totally irrelevant to A and B.
"how I can fix it"
The usual solution is to use indexing. This would be the standard, efficient MATLAB approach:
S(1) = load('dataset1.mat'); % note how indexing makes this trivial in a loop!
S(2) = load('dataset2.mat'); % note how indexing makes this trivial in a loop!
...
for k = 1:numel(S)
S(k).f1 = S(k).rho * S(k).vel1;
end
Importing into separate structures with names A, B, etc. is not recommended and is unlikely to allow efficient handling of your data. It looks like you are trying to write code based on what you know of some other language, but this is rarely a good approach to writing MATLAB code.
3 comentarios
Goncalo Costa
el 12 de Oct. de 2022
Can a for loop be created for the indexing? Something like
for x = 1:4
S(x)= load('dataset(x).mat')
end
I know this is wrong but I am trying to achieve it, and I don't know how.
Stephen23
el 12 de Oct. de 2022
"Can a for loop be created for the indexing?"
Here are several approaches. First lets create some fake data:
X = 1;
Y = 'hello';
save file1.mat X Y
X = 22;
Y = 'happy';
save file2.mat X Y
X = 333;
Y = 'world';
save file3.mat X Y
% check files
clearvars
dir
N = 3;
% 1. Simple but not very robust, assumes S does not exist in workspace.
for k = 1:N
F = sprintf('file%u.mat',k);
S(k) = load(F);
end
display(S)
% 2. Robust if the MAT files contain different variables.
C = cell(1,N);
for k = 1:N
F = sprintf('file%u.mat',k);
C{k} = load(F);
end
S = [C{:}] % however this works only if the fields are the same.
% 4. Using DIR (note the file order might not be what you expect).
S = dir('*.mat');
for k = 1:numel(S)
T = load(S(k).name);
S(k).X = T.X;
S(k).Y = T.Y;
end
display(S)
% 4. On one line (some people like this kind of thing).
S = arrayfun(@(n)load("file"+n+".mat"), 1:N)
Más respuestas (0)
Ver también
Categorías
Más información sobre Function Creation en Help Center y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!