1

Here's a small example of what I want. Given the following array:

1 1 2
2 2 1
1 1 1
1 1 6

Sorted (row sum is shown in parenthesis):

1 1 6 (8)
2 2 1 (5)
1 1 2 (4)
1 1 1 (3)

Is there a quick way to achieve this in Matlab?

remus
  • 2,635
  • 2
  • 21
  • 46
  • 1
    `sort` returns both a sorted matrix and the order / indexing into the original matrix (i.e. sufficient to recreate the original matrix). So just sort on the row sums, and use the ordering to select the rows from the original data. – Bonlenfum Sep 10 '13 at 14:11
  • sort would require a bit more extra work. I found a solution with sortrows (less code). – remus Sep 10 '13 at 14:17

5 Answers5

7

Since sort returns the indexes in order as well as the sorted matrix, you can use these indices to access the original data -- try this:

% some data
A = [
  1 1 2;
  2 2 1;
  1 1 1;
  1 1 6;
];

% compute the row totals
row_totals = sum(A,2);

% sort the row totals (descending order)
[sorted, row_ids] = sort(row_totals, 'descend');

% and display the original data in that order (concatenated with the sums)
disp([A(row_ids,:), row_totals(row_ids)])

>>> 
 1     1     6     8
 2     2     1     5
 1     1     2     4
 1     1     1     3
Bonlenfum
  • 19,101
  • 2
  • 53
  • 56
4

The ugliest one-liner I could come up with:

>> subsref( sortrows( [sum(A,2) A], -1 ), struct('type','()','subs',{{':',1+(1:size(A,2))}}) )

ans =

 1     1     6
 2     2     1
 1     1     2
 1     1     1

Disclaimer: I don't think anyone should write this kind of code, but it's a nice practice to keep your Matlab's skills sharp.

Shai
  • 111,146
  • 38
  • 238
  • 371
2

Just do something very simple like follows

temp = [1 1 2
        2 2 1
        1 1 1
        1 1 6];
rowSums = sum(temp,2);
[~,idx] = sort(rowSums,'descend');
output = [temp(idx,:),rowSums(idx)];

EDIT

Changed the above code to make sure the sum is appended to the last column. I did not notice that this was a requirement when I read the question initially.

MZimmerman6
  • 8,445
  • 10
  • 40
  • 70
  • your edit is not in place, there is no such requirement. If it was, a one-liner was extra simple: `sortrows( [temp, sum(temp,2)], -size(temp,2)+1 )` – Shai Sep 10 '13 at 15:58
  • 1
    oh, well whatever. it is just as easy to remove it as it was to add. So whatever – MZimmerman6 Sep 10 '13 at 16:12
2

I leave it for you to judge if this is uglier than @Shai's:

fliplr(diff([sortrows(fliplr(-cumsum(A,2))) zeros(size(A,1),1) ],1,2))
Luis Mendo
  • 110,752
  • 13
  • 76
  • 147
1

Let's do some matrix multiplication

>> sortrows([sum(A,2) A], -1)*[zeros(1,size(A,2)); eye(size(A,2))]

returns

ans =
     1     1     6
     2     2     1
     1     1     2
     1     1     1
Mohsen Nosratinia
  • 9,844
  • 1
  • 27
  • 52