File Exchange

image thumbnail

nestedSortStruct

version 1.4.0.0 by Jake Hughey
Perform a nested sort of a struct array based on multiple fields.

7 Downloads

Updated 02 Jul 2018

GitHub view license on GitHub

Editor's Note: This file was selected as MATLAB Central Pick of the Week

nestedSortStruct and nestedSortStruct2 do a nested sort of a one-dimensional struct array by two different methods. That is, the struct array is sorted by one field, then those entries of the array that have the same value for that field are sorted by a second field, etc.
If you want to sort by only one field, you can call nestedSortStruct and use a simple string instead of a cell array for fieldNamesCell, or you can simply call sortStruct.
The restrictions are that the fields must be single numbers or logicals, or chars (usually simple strings).

By default the struct array will be sorted in ascending order, but the functions include an option to sort in descending order.

nestedSortStruct will usually be faster than nestedSortStruct2. For nestedSortStruct, the speed of sorting is mostly independent of the order of the fieldnames in fieldNamesCell.

For nestedSortStruct2, the order of the fields in fieldNamesCell affects the speed. The sooner a field for which most entries in the struct array have unique values will be used to sort the struct array (i.e., the earlier its location in fieldNamesCell), the faster nestedSortStruct2 will be. If a field with mostly unique entries is the first field by which the struct array will be sorted, nestedSortStruct2 could be faster than nestedSortStruct.

nestedSortStruct could call sortStruct, and nestedSortStruct2 does call sortStruct2.

Cite As

Jake Hughey (2020). nestedSortStruct (https://github.com/hugheylab/nestedSortStruct), GitHub. Retrieved .

Comments and Ratings (15)

Paramonte

Having a hard time figuring out what is the aStruct format for our case. We get :
Error using nestedSortStruct (line 36)
first input supplied is not a struct.
Our input is a vector of strings.
could you provide an example?

Wenyi Xiao

Hi, Jake

Not enough input arguments.

Error in nestedSortStruct (line 35)
if ~isstruct(aStruct)

I got these error when I run this file. How can I fix it?

Sublime

Jake Hughey

Thanks, Zwithouta. That issue should now be fixed.

Zwithouta

When you have a 1-by-m structure array called myStruct with a field called 'tf' containing a logical, then nestedSortStruct, ignores the request to sort the field descending.

That is:
nestedSortStruct(myStruct, 'tf', 1) == nestedSortStruct(myStruct, 'tf', -1)

To fix this problem I would modify the code as follows (starting line 45 of original code):

Original version:
if isfield(aStruct, fieldNamesCell) % if fieldNamesCell is a simple string of a valid fieldname
[sortedStruct index] = sortStruct(aStruct, fieldNamesCell);
return
else

Fixed version:
if isfield(aStruct, fieldNamesCell) % if fieldNamesCell is a simple string of a valid fieldname
if ~exist('directions')
directions = 1;
end
[sortedStruct index] = sortStruct(aStruct, fieldNamesCell, directions);
return
else

Jake Hughey

You haven't given a reproducible example, but based on the error message, that error is coming from the sortrows function, which is a built-in Matlab function. You should troubleshoot it separately from nestedSortStruct. I don't know if the issue is coming from different numeric data types or not.

One clue to answering my question might be another question: can I sort structs with diff. data types (i.e. integers and doubles). I do not see why that would be a problem, but I expect it could be.

Hi Jake,

I received this error message:

Error using sortrows>sortBackToFrontCell (line 127)
Some cells in X contain non-scalar values and cannot be sorted.

Do you know what X is in this case? I used A and Acell just like in the example.

Thanks,

W

great utility. thanks.

Jake Hughey

Ah, the problem is you're not creating a structure array, you're creating a single structure in which each field is an array.

example1 = struct('name', {'a', 'b', 'c'}, 'time', {1, 2, 3})

example2 = struct
example2.name = {'a', 'b', 'c'}
example2.time = [1, 2, 3]

Notice the difference between these two? nestedSortStruct is designed to handle the first, not the second.

Thanks for the quick reply.

1.Example Code:
example.year(1:10) = 2015
example.lat(1:10) = linspace(1,10,10)
example.lon(1:10) = linspace(1,10,10)
example.curr(1:10) = linspace(1,10,10)
example.time(1:10) = linspace(1,10,10)
datasort = nestedSortStruct(example,{'time'})

The above code gives the same error for me. i.e., "time is not a valid fieldname by which to sort."

2. nestedSortStruct2 gives the same error, with or without cell brackets.

3. Same as 2.

4. R2015b.

Jake Hughey

Jeff - I no longer have access to Matlab, but I can try to help.

1. Can you give me a minimal working example that reproduces the error?
2. Have you tried nestedSortStruct2?
3. Have you tried sortStruct on the individual fields?
4. What version of Matlab are you using?

I am trying to sort a structure with many fields (year,day,month,hour,minute,second,lat,lon,etc) in chronological order. The command I am using is:

datasort = nestedSortStruct(data,{'year','mon','day','hour','min','sec'})

, but I am getting errors saying that all the fieldnames are not valid by which to sort. I have checked, and all the fields are there, and are all doubles. Let me know if you can help me out. Thanks in advance!

Updates

1.4.0.0

No longer ignores directions for sort order.

1.3.0.0

Simplified nestedSortStruct to avoid converting from cell to matrix, resulting in ~20% speedup. Thanks Jori. Fixed minor naming inconsistencies in nestedSortStruct2.

1.2.0.0

Fixed nestedSortStruct so column struct arrays are sorted properly.

1.1.0.0

Minor fix to formatting of initial comments in nestedSortStruct2.m.

MATLAB Release Compatibility
Created with R2008b
Compatible with any release
Platform Compatibility
Windows macOS Linux