1 ## Copyright (C) 2006-2012 Paul Kienzle
3 ## This file is part of Octave.
5 ## Octave is free software; you can redistribute it and/or modify it
6 ## under the terms of the GNU General Public License as published by
7 ## the Free Software Foundation; either version 3 of the License, or (at
8 ## your option) any later version.
10 ## Octave is distributed in the hope that it will be useful, but
11 ## WITHOUT ANY WARRANTY; without even the implied warranty of
12 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 ## General Public License for more details.
15 ## You should have received a copy of the GNU General Public License
16 ## along with Octave; see the file COPYING. If not, see
17 ## <http://www.gnu.org/licenses/>.
20 ## @deftypefn {Function File} {[@var{t}, @var{p}] =} orderfields (@var{s1})
21 ## @deftypefnx {Function File} {[@var{t}, @var{p}] =} orderfields (@var{s1}, @var{s2})
22 ## Return a copy of @var{s1} with fields arranged alphabetically or
23 ## as specified by @var{s2}.
25 ## Given one struct, arrange field names in @var{s1} alphabetically.
27 ## If the second argument is a struct, arrange field names in @var{s1}
28 ## as they appear in @var{s2}. The second argument may also specify the
29 ## order in a permutation vector or a cell array of strings containing
30 ## the fieldnames of @var{s1} in the desired order.
32 ## The optional second output argument @var{p} is assigned the permutation
34 ## which converts the original name order into the new name order.
40 ## s = struct("d", 4, "b", 2, "a", 1, "c", 3);
41 ## t1 = orderfields (s)
51 ## t = struct("d", @{@}, "c", @{@}, "b", "a", @{@});
52 ## t2 = orderfields (s, t)
62 ## t3 = orderfields (s, [3, 2, 4, 1]);
72 ## [t4, p] = orderfields (s, @{"d", "c", "b", "a"@})
88 ## @seealso{getfield, rmfield, isfield, isstruct, fieldnames, struct}
91 ## Author: Paul Kienzle <pkienzle@users.sf.net>
94 function [t, p] = orderfields (s1, s2)
96 if (nargin == 1 || nargin == 2)
98 error ("orderfields: expecting argument to be a struct");
105 ## One structure: return the fields in alphabetical order.
107 names = sort (fieldnames (s1));
111 ## Two structures: return the fields in the order of s2.
112 names = fieldnames (s2);
113 if (! isequal (sort (fieldnames (s1)), sort (names)))
114 error ("orderfields: structures do not have same fields");
116 elseif (iscellstr (s2))
117 ## A structure and a list of fields: order by the list of fields.
118 t1 = sort (fieldnames (s1));
120 if (! isequal (t1, t2))
121 error ("orderfields: name list does not match structure fields");
124 elseif (isvector (s2))
125 ## A structure and a permutation vector: permute the order of s1.
126 names = fieldnames (s1);
129 t2 = 1:numel (names);
130 if (! isequal (t1, t2))
131 error ("orderfields: invalid permutation vector");
137 ## Find permutation vector which converts the original name order
138 ## into the new name order. Note: could save a couple of sorts
139 ## in some cases, but performance isn't critical.
142 [oldel, oldidx] = sort (fieldnames (s1));
143 [newel, newidx] = sort (names);
147 ## Permute the names in the structure.
149 args = cell (1, 2 * numel (names));
150 args(1:2:end) = names;
151 args(2:2:end) = {[]};
152 t = struct (args{:});
155 for i = 1:numel (names)
157 [t(1:n).(el)] = s1(:).(el);
159 ## inherit dimensions
160 t = reshape (t, size (s1));
166 %! a = struct ("foo", {1, 2}, "bar", {3, 4});
167 %! b = struct ("bar", 6, "foo", 5);
168 %! c = struct ("bar", {7, 8}, "foo", 9);
170 %! a(2) = orderfields (b, a);
171 %! assert (a(2).foo, 5)
172 %! assert (a(2).bar, 6)
174 %! [a(2), p] = orderfields (b, [2 1]);
175 %! assert (a(2).foo, 5)
176 %! assert (a(2).bar, 6)
177 %! assert (p, [2; 1]);
179 %! a(2) = orderfields (b, fieldnames (a));
180 %! assert (a(2).foo, 5)
181 %! assert (a(2).bar, 6)
183 %! a(1:2) = orderfields (c, fieldnames (a));
184 %! assert (a(2).foo, 9)
185 %! assert (a(2).bar, 8)
193 %! aa(2) = orderfields (bb, aa);
194 %! assert (aa(2).x, 8);
195 %! assert (aa(2).y{1}, 6);