Increase the number of fields within a 'for' loop?

조회 수: 3 (최근 30일)
Julia Horne
Julia Horne 2018년 3월 15일
댓글: Julia Horne 2018년 3월 19일
I am trying to read a .csv file containing elemental abundances in certain reservoirs, with different units. I want to order this mass of data into a structure that is named 'LITgeo' and contains fields 'species', 'reservoir' and 'unit'. Currently, whenever two different measurements of the same unit go through the loop, the former is replaced by the latter. I want to be able to make my 'unit' field a vector that can contain multiple different measurements in the same units. Here's what I have thus far:
for isp = 1:length(LIT_geosp)
species = LIT_geosp{isp};
reservoir = LIT_geores{isp};
value = LIT_geoval(isp);
unit = LIT_geounit{isp};
LITgeo.(species).(reservoir).(unit)= value ;
end

채택된 답변

Guillaume
Guillaume 2018년 3월 16일
I personally don't like multilevel structures. They're often awkward to use and matlab's display interface for them is lacking. Nowadays, I prefer tables even if it means storing redundant information.
If you stick with multilevel structures, you could check if the field(s) already exist and if so, increase the number of elements. If not, create the fields:
species = LIT_geosp{isp};
reservoir = LIT_geores{isp};
value = LIT_geoval(isp);
unit = LIT_geounit{isp};
if isfield(LITgeo, species) && isfield(LITgeo.(species), reservoir) && isfield(LITgeo.(species).(reservoir), unit)
%the test above will bail out as soon as one of the field is not valid because of the short-circuiting behaviour of &&
&if we get here all fields are valid
LITgeo.(species).(reservoir).(unit)(end+1) = value;
else
%at least unit is new
LITgeo.(species).(reservoir).(unit) = value;
end

추가 답변 (1개)

per isakson
per isakson 2018년 3월 16일
편집: per isakson 2018년 3월 16일
Run
species = 'A';
reservoir = 'B';
unit = 'C';
LITgeo.(species).(reservoir).(unit) = 1;
LITgeo.(species).(reservoir).(unit)(2) = 2;
LITgeo.(species).(reservoir).(unit)(end+1) = 17;
and see the result
>> LITgeo.A.B.C
ans =
1 2 17
  댓글 수: 2
Julia Horne
Julia Horne 2018년 3월 16일
Thanks for the response! I have tried this method, but it requires that I preallocate the struct or, as you have done, enter the values into the struct by hand. I'm hoping to avoid preallocation because I don't want to have to know the size of the .csv file prior to entering the code.
I didn't specify this in my earlier post, but I am using this 'for' loop to then enter my structure into an 'if' loop that compares the unit fieldname to a number of possibilities and then converts the units accordingly (ie. if my LITgeo.(species).(reservoir).(unit) = 'mol', then I enter a loop that changes from mol to grams, etc). In order to retain all the information from the original .csv file, I want to add in empty struct fields that correspond to the units I am converting to in the following step. In my example, this would require that LITgeo.(species).(reservoir).(unit) includes 'grams' as well as 'mol' and any other unit type that is recorded in the .csv file. As my code is currently written, if I enter my conversion loop with a 'unit' field that contains a vector, then the entire vector is overwritten during conversion.
I guess this makes my problem two-pronged: I have to create a 'unit' field in my struct that doesn't overwrite each individual value during generation, while also adding empty fields in which to input the converted values.
Sorry for the long explanation. Here's an example of my conversion loop:
for isp = 1:length(LIT_ocsp)
species = LIT_ocsp{isp};
reservoir = LIT_ocres{isp};
unit = LIT_ocunit{isp};
if strcmp(unit,'Tg')
value = LIT_ocval(isp);
newmol = (value * 1e12) / MolMass.(species);
LIToc.(species).(reservoir).mol(end+1) = newmol;
newuM = newmol * 1e6 / Vol.(reservoir);
LIToc.(species).(reservoir).uM(end+1) = newuM;
elseif strcmp(unit,'wtpct')
for i=length(LIToc.(species).(reservoir).wtpct)
value = LIToc.(species).(reservoir).wtpct(i);
newmol = value * 10000 * Vol.(reservoir) / MolMass.(species);
LIToc.(species).(reservoir).mol(end+1) = newmol;
newuM = newmol * 1e6 / Vol.(reservoir);
LIToc.(species).(reservoir).uM(end+1) = newuM;
end
per isakson
per isakson 2018년 3월 17일
  • "but it requires that I preallocate the struct" see the answer by Guillaume

댓글을 달려면 로그인하십시오.

카테고리

Help CenterFile Exchange에서 Logical에 대해 자세히 알아보기

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by