Jiro's pick this week is Nested Struct Sort by Jake Hughey.
MATLAB has a nice function sortrows to sort matrices (numeric or cells) based on specific column(s). I use it often when I am doing some data management. If you have Statistics Toolbox, there are corresponding functions for dataset arrays and ordinal arrays.
Sometimes, I want to do a similar action on structure arrays. I want to be able to sort according to specific fields. In order to do that, it requires some data manipulations. Let's take a look at an example.
A = struct(... 'name', {'mike', 'doug', 'steve', 'loren', 'jiro', 'brett', 'seth'}, ... 'year', {2005, 2001, 1993, 1987, 2006, 2005, 1998}, ... 'day', {'Mon', 'Fri', 'Wed', 'Fri', 'Mon', 'Mon', 'Mon'}) for id = 1:length(A) fprintf('%d\n',id) disp(A(id)) end
A =
1x7 struct array with fields:
name
year
day
1
name: 'mike'
year: 2005
day: 'Mon'
2
name: 'doug'
year: 2001
day: 'Fri'
3
name: 'steve'
year: 1993
day: 'Wed'
4
name: 'loren'
year: 1987
day: 'Fri'
5
name: 'jiro'
year: 2006
day: 'Mon'
6
name: 'brett'
year: 2005
day: 'Mon'
7
name: 'seth'
year: 1998
day: 'Mon'
Let's sort the array by the field "name". First you need to convert to a cell array:
Afields = fieldnames(A); Acell = struct2cell(A); sz = size(Acell) % Notice that the this is a 3 dimensional array. % For MxN structure array with P fields, the size % of the converted cell array is PxMxN
sz =
3 1 7
Once it's a cell array, you can sort using sortrows:
% Convert to a matrix Acell = reshape(Acell, sz(1), []); % Px(MxN) % Make each field a column Acell = Acell'; % (MxN)xP % Sort by first field "name" Acell = sortrows(Acell, 1)
Acell =
'brett' [2005] 'Mon'
'doug' [2001] 'Fri'
'jiro' [2006] 'Mon'
'loren' [1987] 'Fri'
'mike' [2005] 'Mon'
'seth' [1998] 'Mon'
'steve' [1993] 'Wed'
And convert it back to a structure array:
% Put back into original cell array format Acell = reshape(Acell', sz); % Convert to Struct Asorted = cell2struct(Acell, Afields, 1); for id = 1:length(Asorted) fprintf('%d\n',id) disp(Asorted(id)) end
1
name: 'brett'
year: 2005
day: 'Mon'
2
name: 'doug'
year: 2001
day: 'Fri'
3
name: 'jiro'
year: 2006
day: 'Mon'
4
name: 'loren'
year: 1987
day: 'Fri'
5
name: 'mike'
year: 2005
day: 'Mon'
6
name: 'seth'
year: 1998
day: 'Mon'
7
name: 'steve'
year: 1993
day: 'Wed'
Simpler Approach
Do you want an easier way of doing it? Just use Jake's nestedSortStruct:
B = nestedSortStruct(A, 'name');
isequal(B, Asorted)ans =
1
You can even sort by multiple fields. For example, let's sort by "year" and then by "name":
C = nestedSortStruct(A, {'year', 'name'});
for id = 1:length(C)
fprintf('%d\n',id)
disp(C(id))
end1
name: 'loren'
year: 1987
day: 'Fri'
2
name: 'steve'
year: 1993
day: 'Wed'
3
name: 'seth'
year: 1998
day: 'Mon'
4
name: 'doug'
year: 2001
day: 'Fri'
5
name: 'brett'
year: 2005
day: 'Mon'
6
name: 'mike'
year: 2005
day: 'Mon'
7
name: 'jiro'
year: 2006
day: 'Mon'
Thanks for this entry, Jake. One recommendation I have is to include a couple of examples in the HELP text in the code.
Comments
Give this a try and et us know what you think here or leave a comment for Jake.
Get
the MATLAB code
Published with MATLAB® 7.11


It seems easier to just make use of the index output of sort().
[tmp ind]=sort({A.name}); A=A(ind);Nice one Tom! That does seem easier. And you can expand to multiple field sorting by doing this:
% sort by "year" then "name" [tmp ind] = sortrows([{A.name}',{A.year}'], [2 1]); A = A(ind);The only issue I have is the scalability. If I need to sort by additional fields, I have to dynamically build the SORTROWS command, perhaps using convoluted loops or EVALs.
great !! thanks !!
[tmp ind]=sort({A.name});
A=A(ind);
I get the following error.
x = {Transactions.trtime};
[tmp ind]=sort(x);
??? Error using ==> cell.sort at 55
Input argument must be a cell array of strings
hello pr
if you have that error, use :
sort([struc.field]);
instead of
sort({struc.field});