~gabriel1984sibiu/octave/octave

« back to all changes in this revision

Viewing changes to scripts/miscellaneous/orderfields.m

  • Committer: Grevutiu Gabriel
  • Date: 2014-01-02 13:05:54 UTC
  • Revision ID: gabriel1984sibiu@gmail.com-20140102130554-3r7ivdjln1ni6kcg
New version (3.8.0) from upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
## Copyright (C) 2006-2013 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 as
 
23
## 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} as they
 
28
## appear in @var{s2}.  The second argument may also specify the order in a
 
29
## permutation vector or a cell array of strings containing the fieldnames of
 
30
## @var{s1} in the desired order.
 
31
##
 
32
## The optional second output argument @var{p} is assigned the permutation
 
33
## vector which converts the original name order into the new name order.
 
34
##
 
35
## Examples:
 
36
##
 
37
## @example
 
38
## @group
 
39
## s = struct ("d", 4, "b", 2, "a", 1, "c", 3);
 
40
## t1 = orderfields (s)
 
41
##      @result{} t1 =
 
42
##         @{
 
43
##           a =  1
 
44
##           b =  2
 
45
##           c =  3
 
46
##           d =  4
 
47
##         @}
 
48
## @end group
 
49
## @group
 
50
## t = struct ("d", @{@}, "c", @{@}, "b", @{@}, "a", @{@});
 
51
## t2 = orderfields (s, t)
 
52
##      @result{} t2 =
 
53
##         @{
 
54
##           d =  4
 
55
##           c =  3
 
56
##           b =  2
 
57
##           a =  1
 
58
##         @}
 
59
## @end group
 
60
## @group
 
61
## t3 = orderfields (s, [3, 2, 4, 1])
 
62
##      @result{} t3 =
 
63
##         @{
 
64
##           a =  1
 
65
##           b =  2
 
66
##           c =  3
 
67
##           d =  4
 
68
##         @}
 
69
## @end group
 
70
## @group
 
71
## [t4, p] = orderfields (s, @{"d", "c", "b", "a"@})
 
72
##      @result{} t4 =
 
73
##         @{
 
74
##           d =  4
 
75
##           c =  3
 
76
##           b =  2
 
77
##           a =  1
 
78
##         @}
 
79
##         p =
 
80
##            1
 
81
##            4
 
82
##            2
 
83
##            3
 
84
## @end group
 
85
## @end example
 
86
##
 
87
## @seealso{getfield, rmfield, isfield, isstruct, fieldnames, struct}
 
88
## @end deftypefn
 
89
 
 
90
## Author: Paul Kienzle <pkienzle@users.sf.net>
 
91
## Adapted-By: jwe
 
92
 
 
93
function [t, p] = orderfields (s1, s2)
 
94
 
 
95
  if (nargin == 1 || nargin == 2)
 
96
    if (! isstruct (s1))
 
97
      error ("orderfields: S1 must be a struct");
 
98
    endif
 
99
  else
 
100
    print_usage ();
 
101
  endif
 
102
 
 
103
  if (nargin == 1)
 
104
    ## One structure: return the fields in alphabetical order.
 
105
    if (isstruct (s1))
 
106
      names = sort (fieldnames (s1));
 
107
    endif
 
108
  elseif (nargin == 2)
 
109
    if (isstruct (s2))
 
110
      ## Two structures: return the fields in the order of s2.
 
111
      names = fieldnames (s2);
 
112
      if (! isequal (sort (fieldnames (s1)), sort (names)))
 
113
        error ("orderfields: structures do not have the same fields");
 
114
      endif
 
115
    elseif (iscellstr (s2))
 
116
      ## A structure and a list of fields: order by the list of fields.
 
117
      t1 = sort (fieldnames (s1));
 
118
      t2 = sort (s2(:));
 
119
      if (! isequal (t1, t2))
 
120
        error ("orderfields: name list does not match structure fields");
 
121
      endif
 
122
      names = s2;
 
123
    elseif (isvector (s2))
 
124
      ## A structure and a permutation vector: permute the order of s1.
 
125
      names = fieldnames (s1);
 
126
      t1 = sort (s2);
 
127
      t1 = t1(:)';
 
128
      t2 = 1:numel (names);
 
129
      if (! isequal (t1, t2))
 
130
        error ("orderfields: invalid permutation vector");
 
131
      endif
 
132
      names = names(s2);
 
133
    endif
 
134
  endif
 
135
 
 
136
  ## Corner case of empty struct
 
137
  if (isempty (names))
 
138
    t = struct ();
 
139
    p = [];
 
140
  endif
 
141
 
 
142
  ## Find permutation vector which converts the original name order
 
143
  ## into the new name order.  Note: could save a couple of sorts
 
144
  ## in some cases, but performance isn't critical.
 
145
 
 
146
  if (nargout == 2)
 
147
    [~, oldidx] = sort (fieldnames (s1));
 
148
    [~, newidx] = sort (names);
 
149
    p = oldidx(newidx);
 
150
  endif
 
151
 
 
152
  ## Permute the names in the structure.
 
153
  if (numel (s1) == 0)
 
154
    args = cell (1, 2 * numel (names));
 
155
    args(1:2:end) = names;
 
156
    args(2:2:end) = {[]};
 
157
    t = struct (args{:});
 
158
  else
 
159
    n = numel (s1);
 
160
    for i = 1:numel (names)
 
161
      el = names{i};
 
162
      [t(1:n).(el)] = s1(:).(el);
 
163
    endfor
 
164
    ## inherit dimensions
 
165
    t = reshape (t, size (s1));
 
166
  endif
 
167
 
 
168
endfunction
 
169
 
 
170
 
 
171
%!shared a, b, c
 
172
%! a = struct ("foo", {1, 2}, "bar", {3, 4});
 
173
%! b = struct ("bar", 6, "foo", 5);
 
174
%! c = struct ("bar", {7, 8}, "foo", 9);
 
175
%!test
 
176
%! a(2) = orderfields (b, a);
 
177
%! assert (a(2).foo, 5);
 
178
%! assert (a(2).bar, 6);
 
179
%!test
 
180
%! [a(2), p] = orderfields (b, [2 1]);
 
181
%! assert (a(2).foo, 5);
 
182
%! assert (a(2).bar, 6);
 
183
%! assert (p, [2; 1]);
 
184
%!test
 
185
%! a(2) = orderfields (b, fieldnames (a));
 
186
%! assert (a(2).foo, 5);
 
187
%! assert (a(2).bar, 6);
 
188
%!test
 
189
%! a(1:2) = orderfields (c, fieldnames (a));
 
190
%! assert (a(2).foo, 9);
 
191
%! assert (a(2).bar, 8);
 
192
 
 
193
%!test
 
194
%! aa.x = {1, 2};
 
195
%! aa.y = 3;
 
196
%! aa(2).x = {4, 5};
 
197
%! bb.y = {6, 7};
 
198
%! bb.x = 8;
 
199
%! aa(2) = orderfields (bb, aa);
 
200
%! assert (aa(2).x, 8);
 
201
%! assert (aa(2).y{1}, 6);
 
202
 
 
203
## Corner case of empty struct, bug #40224
 
204
%!assert (orderfields (struct ()), struct ())
 
205