How to use dot notation (substructures and fields) with a parameter which has already "dot" in it??

Hello everyone I am new at matlab, so I think this is a very basic thing but I couldn't solve this.
I have 1x1 cells that contains field names(which they are also 1x1 substruct) of the 1x1 structure. I want to access these substructs and "their" fields with 1x1 cells, because I don't want to write all the field names one by one; I get the cells with get_param function, and I intend to use them with getfield function.
For example; Let's say main structure is " EXC " and substructure is " abc " and I want to get " data " field of abc substructure. I have " abc " field name as a 1x1 cell let's say " conS ". So I write this and I can get the data without problem;
getfield(EXC.(conS{1}), 'data')
ans =
1 0 (for example)
no problem as far but problem begins with when field name, named with also "dot" like " EXC. def ". Let's say this 1x1 cell " conR". When I use cells that have field names starting with " EXC.~~" the code does'nt work, gives this error;
getfield(EXC.(conR{1}), 'data')
Reference to non-existent field 'EXC.def'.
But when I write " EXC.def.data ", I can acces to data...
EXC.def.data
ans =
1 2 (for example)
Normally I have nx1 cells that have field names and some of them have "EXC." at their front and some of them don't have. But I need to use all of them with getfield ( or some other function) in a for loop to get their data one by one.
How can I do this? How can I use these cells that have "EXC.~~" with getfield function? or are there any other function I can use to do all of this, I really appreciate your help as I am beginner of MATLAB.
Thanks in advance, I hope I made it clear, you can ask anything that you couldn't figure out.

 채택된 답변

dpb
dpb 2017년 10월 15일
Short answer is "you can't do that!". The field name in the variable has to be a single field and a field name can't have an embedded dot within it. It's just illegal syntax and there is no way around that that is anything will recommend as a solution (even to a veteran user and certainly to a novice, anyway).
The solution is to remove the dot from the cell; if you're really trying to read an existing field but that is a field of the first such that there are two dots to dereference it as your working text example from command line, then store those as separate variables; don't try to combine them.
I'd suggest it may be you're nesting too deeply if you're running into this problem or perhaps trying to store the data in other overly-complex manner that there's a much easier solution but we can't tell much about that without more background on what you actually started with and what you're trying to accomplish.

댓글 수: 10

Thank you for your answer.
Yeah , well, I have a simulink file that contains so many "custom" blocks.. These blocks are linked to a "EXC.mat" file, that is my main 1x1 structure. Blocks that I interested have two parameters as "Variable name (field name of EXC struct array)" such as "abc" or "EXC.def" and "Value" such as "abc.data" or "EXC.def.data".
The main thing I want to do: some of these values at "EXC.mat" are corrupted, lack of name or data, in that condition simulation at simulink doesn't work, so I need to define these corrupted fields and their structures and write to an excel file to document these.
I interested in a block type so first of all I find that blocks with
con = find_system('EXC', 'MaskType', 'con')
Then I write for loop,
for k = 1:length(con)
conR = get_param(con(k), 'constant'); %(constant is parameter for the name)
if getfield(EXC.(conR{1}), 'data') == [] %(I am also not sure about this [] I want it to represent "empty")
xlswrite('exc.xlsx', conR)
end
end
this works for conR arrays that don't have cell(name) starts with 'EXC.~~'.
I could use isfield too but I don't think it will work with these 'EXC.~~'.
Also, I don't know how to remove 'EXC.' from these cells, or from the block parameters, I don't think I am neither capable to write a script that does that, I come with the idea of using set_param but I don't know how to define and set apart every block that has 'EXC.' on their parameters. if you have any idea I [would] appreciate it.
You can create fieldnames, which contain dots, inside C-Mex functions. Accessing the field 'b.c' does not work by S.b.c then, because Matlab separates the levels at the dot. But S.('b.c') will work. You can use the full range of the 8Bit-CHAR type as characters, even the empty string.
But of course, you should not do this. It is tweaking and squeezing the Matlab standards. The resulting code will be incompatible and instable.
Using valid Matlab names is the correct way. +1
@Burak: If you want to store the string "EXC.~~", use an extra field:
S.Data = 123
S.Name = 'EXC.~~'
Hiding useful information in the names of variables or fields is less efficient and a bad idea.
@Jan Simon , Thank you for your comment,
I think I could'nt explain it clearly, in structure its name is not "EXC.def" it is still "def" but in block parameters it is "EXC.def" and I get cell arrays from these block parameters.
So I have 1x1(or nx1) cell with field "EXC.def" with that I need to access "def" substructure and its fields. normally I get "def" from block parameters and everything works perfectly but some of the block parameters starts with "EXC." that is the problem.
also above I tried to explain what I am trying to accomplish, if you interested you can take a look.
for k = 1:length(con)
conR = get_param(con(k), 'constant'); %(constant is parameter for the name)
if getfield(EXC.(conR{1}), 'data') == []
%(I am also not sure about this [] I want it to represent "empty")
The above should be
if isempty(getfield(EXC.(conR{1}), 'data'))
I don't have Simulink so "know nuthink!" about what get_param returns.
But, if I get the drift of the desire, looks like what you need to do is related to my original comment regarding too much depth in indexing...I'd think going back to how the aforementioned .mat file was created may be the better solution to the problem you're now having and parsing that data first instead of reading the .mat file--that has introduced another level of indirection by having that structure. If you start with the data that was put into the .mat file first, I'm guessing it'll be easier to parse to get what it is you're after...
But, may take somebody with Simulink that can work directly with the actual results returned for a given model to actually be able to provide the cleaner solution...and, given I don't have (and have never seen) Simulink, that's not I... :)
@dpb; Thank you for your suggestion about isempty, I will try it.
get_param returns exactly what is written in defined block paramater, in my case it is exactly "abc" or "EXC.def" like;
>> conR
conR =
'EXC.def' ( or 'def' if block parameter does'nt contain EXC. in front)
So, what's the specific problem again? You just want/need the 'def' substring rather than the full string? Or, do you need the "pieces-parts" of the string? That's simple enough
>> conR = 'EXC.def';
>> strsplit(conR,'.')
ans =
'EXC' 'def'
>> conR = 'def';
>> strsplit(conR,'.')
ans =
'def'
>>
@dpb; yeah you were right, "that can't be done" and the thing is that cells start with 'EXC.' were all corrupted. I get them with isfield function and then if the field exist, I checked its data with elseif and isempty function.
if isfield(EXC, conR) == 0
xlswrite('excstj.xlsx', conR)
elseif isempty(EXC.(conR{1}).data) == 1
xlswrite('excstj.xlsx', conR)
end
now everthing seems okay, expect xlswrite function, I am just learning matlab so I need to look more about how to use xlswrite in loops and how to design it.. if you have any suggestion about xlswrite for this example, I appriciate it.
thanks!
@dpb now everything is ok and I don't need to rip the cell apart, but yeah I thought that I had to, and strsplit would be very good, but also I tried that and it didn't work for cell I get the error: Undefined function 'strsplit' for input arguments of type 'cell'.
But now I don't need to do that, all is well.
"Undefined function 'strsplit' for input arguments of type 'cell'."
You have to dereference the cellstr content with the curlies...
if isfield(EXC, conR) == 0
xlswrite('excstj.xlsx', conR)
elseif isempty(EXC.(conR{1}).data) == 1
xlswrite('excstj.xlsx', conR)
end
Don't know the purpose here, but the two condition tests don't really do anything since the code is the same either way inside...perhaps you're trying to not do anything if both are false???
if ~isfield(EXC, conR) | isempty(EXC.(conR{1}).data)
xlswrite('excstj.xlsx', conR)
end
NB: Don't need the specific '==Value' for a logical test; the condition is True if ~0 and False if 0. The result of
if condition==1
is simply
if _value_
where value is the result of the expression condition==1 which just reduces to either 0 or 1 anyway. The ==0|1 is just superfluous. Only if you were comparing a value to a specific choice out of a set of alternatives such as 1 to N would it be necessary (which could like be better written as a SWITCH block anyways).

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

추가 답변 (0개)

카테고리

질문:

2017년 10월 15일

댓글:

dpb
2017년 10월 15일

Community Treasure Hunt

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

Start Hunting!

Translated by