-
Notifications
You must be signed in to change notification settings - Fork 3
/
fieldnamesr.m
177 lines (156 loc) · 6.23 KB
/
fieldnamesr.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
function NAMES = fieldnamesr(S,varargin)
%FIELDNAMESR Get structure field names in recursive manner.
%
% NAMES = FIELDNAMESR(S) returns a cell array of strings containing the
% structure field names associated with s, the structure field names
% of any structures which are fields of s, any structures which are
% fields of fields of s, and so on.
%
% NAMES = FIELDNAMESR(S,DEPTH) is an optional field which allows the depth
% of the search to be defined. Default is -1, which does not limit the
% search by depth. A depth of 1 will return only the field names of s
% (behaving like FIELDNAMES). A depth of 2 will return those field
% names, as well as the field names of any structure which is a field of
% s.
%
% NAMES = FIELDNAMESR(...,'full') returns the names of fields which are
% structures, as well as the contents of those structures, as separate
% cells. This is unlike the default where a structure-tree is returned.
%
% NAMES = FIELDNAMESR(...,'prefix') returns the names of the fields
% prefixed by the name of the input structure.
%
% NAMES = FIELDNAMESR(...,'struct') returns only the names of fields
% which are structures.
%
% See also FIELDNAMES, ISFIELD, GETFIELD, SETFIELD, ORDERFIELDS, RMFIELD.
% Developed in MATLAB 7.13.0.594 (2011b).
% By AATJ (adam.tudorjones@pharm.ox.ac.uk). 2011-10-11. Released under
% the BSD license.
%Set optional arguments to default settings, if they are not set by the
%caller.
if size(varargin,1) == 0
optargs = {-1} ;
optargs(1:length(varargin)) = varargin ;
depth = optargs{:} ;
full = [0] ; [prefix] = [0] ; [struct] = [0] ;
else
if any(strcmp(varargin,'full') == 1)
full = 1 ;
else
full = 0 ;
end
if any(strcmp(varargin,'prefix') == 1)
prefix = 1 ;
else
prefix = 0 ;
end
if any(strcmp(varargin,'struct') == 1)
struct = 1 ;
else
struct = 0 ;
end
if any(cellfun(@isnumeric,varargin) == 1)
depth = varargin{find(cellfun(@isnumeric,varargin))} ;
else
depth = -1 ;
end
end
%Return fieldnames of input structure, prefix these with "S.".
NAMES = cellfun(@(x) strcat('S.',x),fieldnames(S),'UniformOutput',false) ;
%Set state counters to initial values (k terminates recursive loop, g makes
%recursive loop behave in a different way.
k = 1 ; g = 0 ;
fndstruct = {} ;
%k is ~0 while all fields have not been searched to exhaustion or to
%specified depth.
while k ~= 0
fndtemp = {} ;
k = length(NAMES) ;
%g set to 1 prevents fieldnames from being added to output NAMES.
%Useful when determining whether fields at the lowest specified depth
%are structures, without adding their child fieldnames (i.e. at
%specified depth + 1) to NAMES output.
if depth == 1
g = 1 ;
end
for i = 1:length(NAMES)
%If the current fieldname is a structure, find its child
%fieldnames, add to NAMES if not at specified depth (g = 0). Add to
%fndstruct (list of structures).
if isstruct(eval(NAMES{i})) == 1
if g ~= 1
fndtemp2 = fieldnames(eval(NAMES{i})) ;
fndtemp2 = cellfun(@(x) strcat(sprintf('%s.' ...
,NAMES{i}),x),fndtemp2,'UniformOutput',false) ;
fndtemp = cat(1,fndtemp,fndtemp2) ;
elseif g == 1
fndtemp = cat(1,fndtemp,NAMES{i}) ;
k = k - 1 ;
end
fndstruct = cat(1,fndstruct,NAMES{i}) ;
else
fndtemp = cat(1,fndtemp,NAMES{i}) ;
k = k - 1 ;
end
end
NAMES = fndtemp ;
%If we have reached depth, stop recording children fieldnames to NAMES
%output, but determine whether fields at final depth are structures or
%not (g). After this, terminate loop by setting k to 0.
if depth ~= -1 ...
&& any(cellfun(@(x) size(find(x == '.'),2),NAMES) == depth)
g = 1 ;
elseif depth ~= -1 ...
&& any(cellfun(@(x) size(find(x == '.'),2),NAMES) > depth)
k = 0 ;
end
end
%Return names of fields which are structures, as well as fields which are
%not structures, if 'full' optional argument is set.
if full == 1
for i = 1:length(fndstruct)
%If depth is specified, add structure names to appropriate depth to
%output NAMES.
if depth == -1 || size(find(fndstruct{i} == '.'),2) <= depth-1
structi = find(cellfun(@(x) isempty(x) == 0 ...
,strfind(NAMES,fndstruct{i})),1) ;
%If the current structure name is related to the first field of
%NAMES, add structure name to NAMES in a particular way, else
%add it in another way.
if structi > 1
NAMES = cat(1,NAMES(1:(structi-1)),fndstruct{i} ...
,NAMES(structi:end)) ;
elseif isempty(structi)
error ('AATJ:fieldnamesr,NotFindStructure' ...
,'Could not find structure name in NAMES') ;
else
NAMES = cat(1,fndstruct{i},NAMES) ;
end
end
end
end
%Return only fields which are structures, if optional argument is defined.
%If 'full' is not set, do not include both parent and child structures.
if struct == 1
if full == 0
fndstruct2 = {} ;
for i = 1:length(fndstruct)
if isempty(cell2mat(strfind(fndstruct,strcat(fndstruct{i},'.')))) == 1
fndstruct2(end+1,1) = fndstruct(i) ;
end
end
fndstruct = fndstruct2 ;
end
NAMES = fndstruct ;
end
%Prefix input structure name on all fields of output cell array NAME if
%user set this option.
if prefix == 1
structname = inputname(1) ;
NAMES = cellfun(@(x) strcat(sprintf('%s.',structname),x(3:end)) ...
,NAMES,'UniformOutput',false) ;
else
NAMES = cellfun(@(x) sprintf('%s',x(3:end)),NAMES,'UniformOutput' ...
,false) ;
end