views:

78

answers:

3
+2  Q: 

Sorting in Matlab

Hi,

I would like to sort elements in a comma-separated list. The elements in the list are structs and I would like the list to be sorted according to one of the fields in the struct.

For example, given the following code:

 L = {struct('obs', [1 2 3 4], 'n', 4), struct('obs', [6 7 5 3], 'n', 2)};

I would want to have a way to sort L by the field 'n'. Matlab's sort function only works on matrices or arrays and on lists of strings (not even lists of numbers).

Any ideas on how that may be achieved?

Thanks,

Micha

+6  A: 

I suggest you do this in three steps: Extract 'n' into an array, sort the array and consequently reorder the elements of the cell array.

%# get the n's
nList = cellfun(@(x)x.n,L);

%# sort the n's and capture the reordering in sortIdx
[sortedN,sortIdx] = sort(nList);

%# use the sortIdx to sort L
sortedL = L(sortIdx)
Jonas
if you're using the newest version of MATALB you can do `[~, sortIdx] = sort(nList);`. That way you don't have an extra variable lying around.
JudoWill
@JudoWill: Great new feature, but I found out it's not backwards compatible the hard way a while ago. Some of my co-workers have older versions of MATLAB, and my code came to a screeching halt when they tried to run it.
Doresoom
@JudoWill: I like the feature, and I'll probably start using it 2-3 years from now.
Jonas
+1  A: 

For what it's worth, here is the solution in Python:

L = [{'n': 4, 'obs': [1, 2, 3, 4]}, {'n': 2, 'obs': [6, 7, 5, 3]}]
L.sort(lambda a,b: a['n'].__cmp__(b['n']))
# L is now sorted as you wanted
Olivier
+2  A: 

This is a bit of an aside, but if all of the structures in your cell array L have the same fields (obs and n in this case), then it would make more sense to store L as a 1-by-N structure array instead of a 1-by-N cell array of 1-by-1 structures.

To convert the 1-by-N cell array of structures to a 1-by-N structure array, you can do the following:

L = [L{:}];

Or, you can create the structure array directly using one call to STRUCT instead of creating the cell array of structures as you did in your example:

L = struct('obs',{[1 2 3 4],[6 7 5 3]},'n',{4,2});

Now the solution from Jonas becomes even simpler:

[junk,sortIndex] = sort([L.n]);  %# Collect field n into an array and sort it
sortedL = L(sortIndex);          %# Apply the sort to L
gnovice
+1 for simplifying the question first
Jonas