Search within a structure using a string

Hello Im trying to check if a string exist within a strucure:
The string is the structure path, which I created using sprintf I can not detect if the string coincide with the path of an existent structure in the workspace (Clicks).
Eval dosent work for structures neither fieldnames ... there is any way to check if exist or not in the workspace???
thanks in advance
prof_l=unique(prof_list);
shore_l=unique(shore_list);
% read clicks and extract shoreline
met=('fix');
%
for i1=1:numel(prof_l)
p=prof_l(i1,1);
for i2=1:1:numel(shore_l)
s=shore_l(i2,1);
file=(sprintf('Clicks.prof_%u.shore_%u.%s',p,s,met));
if exist(eval(file),var) ==1;
disp('hola')
end
end
end

 Accepted Answer

Here is the test you asked for. I would point out that if the answer is True, that the structure exists, chances are high that you are planning to use eval() to get at the value stored, and that you should be strongly avoiding doing that.
function tf = struct_exists(candidate)
%Written 20150905 - Walter Roberson
%{
Here is a structure exist. In this version it *only* handles flat structures, no
indexing, no dynamic fieldnames.
The empty string and [] are accepted as valid arguments (and return false). Other
non-string arguments will generate a warning (and false)
The last field given is _not_ tested to see if it is a structure (only whether it
exists) so that this routine can be used to test whether a field exists. As a design
decision this extends to the case where the passed name has no subfields given and
so is the last field name given: in this case true is returned if the name exists
whether or not the name is a structure.
The use of warnings instead of error was a design decision, one that is most
debatable for the case of invalid input. I used warnings because this is
supposed to be an existence test, and if the answer is "No that is not a valid
arrangement of structure references" then Okay, that's why you *tested* rather
than just went ahead and used the string.
%}
tf = false;
if ~( ischar(candidate) || (isdouble(candidate) && isempty(candidate)) )
warning('struct_exist: only character strings or [] permitted as argument')
return
end
if isempty(candidate); return; end
if regexp(candidate, '[^a-zA-z0-9_.]')
warning('struct_exist: only fieldnames and ''.'' permitted');
return;
end
parts = regexp(candidate, '\.', 'split');
if ~ evalin('caller', sprintf('exist(''%s'', ''var'')', parts{1}));
warning( sprintf('struct_exist, "%s" is not a variable', parts{1}) );
return;
end
for K = 1 : length(parts) - 1
subname = strjoin(parts(1:K), '.');
try
fn = evalin('caller', sprintf('fieldnames(%s)', subname));
catch ME
%some leading fieldname was not a structure
fn = {};
end
if ~ismember(parts{K+1}, fn)
%some leading prefix does not have the next part as a field
% no warning because this is a normal use case
return
end
end
tf = true;
end

1 Comment

thanks Walter, interesting is the slipt between substructures

Sign in to comment.

More Answers (1)

Try
>> S.a.b.c = 'abc';
>> S.('a').('b').c
ans =
abc
and
str = Clicks.( sprintf('prof_%u',p) ).( sprintf('shore_%u',s) ).met;
if exist( str, 'var' ) == 1
disp('hola')
end

6 Comments

Your methods give an error with exist that is not designed for structures :(
i solve it in a very dirty way, by using try...
doesVarExist = true
try
Clicks.(sprintf('prof_%u',p)).(sprintf('shore_%u',s)).method;
catch
doesVarExist = false
end
if doesVarExist == 1
wierd that matlab not includes this type of routines for work with structures...
"Your methods give an error with exist that is not designed for structures" &nbsp I think my method is sound! My problem is that I have to backward engineer your code.
I assume that the value of Clicks.prof1.shore2.met is a string. (Note that I just picked 1 and 2.) That's why I assigned the value to a variable called str. Next, I assumed that you want to test whether there exists a variable, the name of which is the value of str.
Your "try-catch-end" construct tests whether the fields exist. That is best done with the function isfield.
Please don't write "give an error" without further detail. It's just not helpful.
Hey thanks a lot for your help
I think this happens with any structure array in matlab, not only with my specific case, I think "exist" fails because matlab can not detect an existing array inside a structure
check this, based in your example:
a.b.c.d='ABC'
exist(a.b.c.d) %Ok, works with the entire structure
ans =
0
exist(a.b.c) %but fails when I'm trying to detect a substructure
Undefined function 'exist' for input
arguments of type 'struct'.
"I think "exist" fails" &nbsp See exist, Check existence of variable, function, folder, or class. That's right, exist cannot test for existence of fields in a structure. There is a special function for that, isfield
>> S.a.b.c = 'abc';
>> isfield( S.a.b, 'c' )
ans =
1
>> isfield( S.a.b, 'd' )
ans =
0
>> isfield( S, 'a' )
ans =
1
>> isfield( S, 'z' )
ans =
0
Note that the values of S.a.b and S are structures.
>> S.a.b.c = 'abc'; %isfield "FAILS" in the attemp to check a substructure inside the structure. obtaining 0 all the time
%
>> isfield( S.a.b, 'c' ) %ok it works with a single string
ans =
1
>> isfield( S.a.b, 'S.a' )%lets test a complex string
ans =
0
>> isfield( S, 'S.a' )
ans =
0
PD:
isfield( S, 'S'.'a' )
isfield( S, 'S'.'a' )
|
Error: Unexpected MATLAB expression.
"in the attemp to check a substructure inside the structure" &nbsp I don't understand what exactly you want to check. In plain English, what is your intention with
isfield( S.a.b, 'S.a' )
isfield( S, 'S.a' )
Under what circumstances should they return true and false, respectively? &nbsp 'S.a' isn't a legal field name.
&nbsp
To check whether a value is a structure use isstruct
>> isstruct( S )
ans =
1
>> isstruct( S.a )
ans =
1
>> isstruct( S.a.b )
ans =
1
>> isstruct( S.a.b.c )
ans =
0
>> ischar( S.a.b.c )
ans =
1
>>

Sign in to comment.

Categories

Community Treasure Hunt

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

Start Hunting!