]> Creatis software - CreaPhase.git/blob - octave_packages/m/miscellaneous/orderfields.m
update packages
[CreaPhase.git] / octave_packages / m / miscellaneous / orderfields.m
1 ## Copyright (C) 2006-2012 Paul Kienzle
2 ##
3 ## This file is part of Octave.
4 ##
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.
9 ##
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.
14 ##
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/>.
18
19 ## -*- texinfo -*-
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}.
24 ##
25 ## Given one struct, arrange field names in @var{s1} alphabetically.
26 ##
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.
31 ##
32 ## The optional second output argument @var{p} is assigned the permutation
33 ## vector
34 ## which converts the original name order into the new name order.
35 ##
36 ## Examples:
37 ##
38 ## @example
39 ## @group
40 ## s = struct("d", 4, "b", 2, "a", 1, "c", 3);
41 ## t1 = orderfields (s)
42 ##      @result{} t1 =
43 ##         @{
44 ##           a =  1
45 ##           b =  2
46 ##           c =  3
47 ##           d =  4
48 ##         @}
49 ## @end group
50 ## @group
51 ## t = struct("d", @{@}, "c", @{@}, "b", "a", @{@});
52 ## t2 = orderfields (s, t)
53 ##      @result{} t2 =
54 ##         @{
55 ##           d =  4
56 ##           c =  3
57 ##           b =  2
58 ##           a =  1
59 ##         @}
60 ## @end group
61 ## @group
62 ## t3 = orderfields (s, [3, 2, 4, 1]);
63 ##      @result{} t3 =
64 ##         @{
65 ##           a =  1
66 ##           b =  2
67 ##           c =  3
68 ##           d =  4
69 ##         @}
70 ## @end group
71 ## @group
72 ## [t4, p] = orderfields (s, @{"d", "c", "b", "a"@})
73 ##      @result{} t4 =
74 ##         @{
75 ##           d =  4
76 ##           c =  3
77 ##           b =  2
78 ##           a =  1
79 ##         @}
80 ##         p =
81 ##            1
82 ##            4
83 ##            2
84 ##            3
85 ## @end group
86 ## @end example
87 ##
88 ## @seealso{getfield, rmfield, isfield, isstruct, fieldnames, struct}
89 ## @end deftypefn
90
91 ## Author: Paul Kienzle <pkienzle@users.sf.net>
92 ## Adapted-By: jwe
93
94 function [t, p] = orderfields (s1, s2)
95
96   if (nargin == 1 || nargin == 2)
97     if (! isstruct (s1))
98       error ("orderfields: expecting argument to be a struct");
99     endif
100   else
101     print_usage ();
102   endif
103
104   if (nargin == 1)
105     ## One structure: return the fields in alphabetical order.
106     if (isstruct (s1))
107       names = sort (fieldnames (s1));
108     endif
109   elseif (nargin == 2)
110     if (isstruct (s2))
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");
115       endif
116     elseif (iscellstr (s2))
117       ## A structure and a list of fields: order by the list of fields.
118       t1 = sort (fieldnames (s1));
119       t2 = sort (s2(:));
120       if (! isequal (t1, t2))
121         error ("orderfields: name list does not match structure fields");
122       endif
123       names = s2;
124     elseif (isvector (s2))
125       ## A structure and a permutation vector: permute the order of s1.
126       names = fieldnames (s1);
127       t1 = sort (s2);
128       t1 = t1(:)';
129       t2 = 1:numel (names);
130       if (! isequal (t1, t2))
131         error ("orderfields: invalid permutation vector");
132       endif
133       names = names (s2);
134     endif
135   endif
136
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.
140
141   if (nargout == 2)
142     [oldel, oldidx] = sort (fieldnames (s1));
143     [newel, newidx] = sort (names);
144     p = oldidx(newidx);
145   endif
146
147   ## Permute the names in the structure.
148   if (numel (s1) == 0)
149     args = cell (1, 2 * numel (names));
150     args(1:2:end) = names;
151     args(2:2:end) = {[]};
152     t = struct (args{:});
153   else
154     n = numel (s1);
155     for i = 1:numel (names)
156       el = names(i);
157       [t(1:n).(el)] = s1(:).(el);
158     endfor
159     ## inherit dimensions
160     t = reshape (t, size (s1));
161   endif
162
163 endfunction
164
165 %!shared a, b, c
166 %! a = struct ("foo", {1, 2}, "bar", {3, 4});
167 %! b = struct ("bar", 6, "foo", 5);
168 %! c = struct ("bar", {7, 8}, "foo", 9);
169 %!test
170 %! a(2) = orderfields (b, a);
171 %! assert (a(2).foo, 5)
172 %! assert (a(2).bar, 6)
173 %!test
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]);
178 %!test
179 %! a(2) = orderfields (b, fieldnames (a));
180 %! assert (a(2).foo, 5)
181 %! assert (a(2).bar, 6)
182 %!test
183 %! a(1:2) = orderfields (c, fieldnames (a));
184 %! assert (a(2).foo, 9)
185 %! assert (a(2).bar, 8)
186
187 %!test
188 %! aa.x = {1, 2};
189 %! aa.y = 3;
190 %! aa(2).x = {4, 5};
191 %! bb.y = {6, 7};
192 %! bb.x = 8;
193 %! aa(2) = orderfields (bb, aa);
194 %! assert (aa(2).x, 8);
195 %! assert (aa(2).y{1}, 6);