2011-04-13 100 views
4

讓我們說你有一個一維矩陣MATLAB通過索引排序的2D和3D矩陣和訪問

a = rand(1,5); 
[sa i] = sort(a); 

然後saa(i)是相同的。然而,如果基質的尺寸增加

a = rand(3,4); 
[sa i] = sort(a); 

然後saa(i)是不一樣的。而當我嘗試按照第三維排序3D矩陣時也會發生同樣的情況。

如何通過索引i訪問a的值?換句話說,我該如何計算sa=a(X)X應該是什麼?

編輯:

感謝您的解決方案。但是,當您更改維度進行排序時,它們不起作用。不過,我拿起這個想法並用它來構建一個通用表單。

算法做的是建立矩陣的索引。 MATLAB明確列出單元格列。因此,索引是由

idx = r + (c-1)*ROWS + (p-1)*ROWS*COLS 

其中,idx給出是索引,r是行位置,c是列位置,並且p是頁位置。

因此,如果我們在第一維(普通sort(a))中排序,結果索引是列中的位置;如果我們在第二維中排序,結果索引是行中的位置;如果我們在第三維中排序,那麼結果索引就是頁面位置。這是說,它只能維持生產行列數爲給定的情況下:

r = repmat((1:rows)',[1 cols pages]); 
c = repmat(1:cols,[rows 1 pages]); 

在第一維排序中給出的解決方案進行了說明。隨後,讓在第二維二維數組排序(行明智)現在

a = rand(4,5); 
[rows cols pages] = size(a); 
R = repmat((1:rows)',[1 cols pages]); 
[sa idx] = sort(a,2); 
nIdx = R + (idx-1)*rows; 
isequal(sa,a(nIdx)) 

,如果我們使用同樣的想法在第三維度排序(頁明智的),我們需要做的

a = rand(4,5,3); 
[rows cols pages] = size(a); 
R = repmat((1:rows)',[1 cols pages]); 
C = repmat(1:cols,[rows 1 pages]); 
[sa idx] = sort(a,3); 
nIdx = R + (C-1)*rows + (idx-1)*rows*cols; 
isequal(sa,a(nIdx)) 

而且可以使用相同的邏輯將其擴展到N維。 感謝您的幫助,您點亮了方向。 :)

+0

爲2D和3D最好的答案就在這裏。 – Trefex 2014-05-26 09:53:52

回答

4

[sa, i]=sort(a)返回有序索引的每列。您只需要獲得矩陣的正確線性索引。因此,對於一個二維矩陣,

A=rand(3,4); 
[rows,cols]=size(A); 
[B,index]=sort(A,1); 
correctedIndex=index+repmat(0:cols-1,rows,1)*rows; 

現在測試一下:

A = 

    0.9572 0.1419 0.7922 0.0357 
    0.4854 0.4218 0.9595 0.8491 
    0.8003 0.9157 0.6557 0.9340 

B = 

    0.4854 0.1419 0.6557 0.0357 
    0.8003 0.4218 0.7922 0.8491 
    0.9572 0.9157 0.9595 0.9340 

A(correctedIndex) 

ans = 

    0.4854 0.1419 0.6557 0.0357 
    0.8003 0.4218 0.7922 0.8491 
    0.9572 0.9157 0.9595 0.9340 
+0

另外,你還可以看看'sortrows'函數,它的第二個輸出參數可以用來實現類似'sa = a(i,:)'的東西,用你的符號。 – abcd 2011-04-13 04:12:00

+0

謝謝,你把我放在正確的方向。我知道如何使用索引。我擴展您的解決方案,使其適用於任何維度的排序。 thx – adn 2011-04-13 08:12:08

1
a = rand(3,5); 
[sa i] = sort(a); 
ii=bsxfun(@plus,i,0:size(a,1):numel(a)-size(a,1)); 
isequal(a(ii),sa) 
1

您可以創建一個一般的矢量化的解決方案,適用於任何ND矩陣工作或使用功能IND2SUB排序維和SUB2IND。在這裏,我將這個解決方案打包成一個新函數sort_linear_index,它的功能與函數SORT相似,只是它將返回線性索引,因此無論A的大小是多少,B = A(IX)都將始終有效。

function [sortedA,sortIndex] = sort_linear_index(A,sortDim,sortOrder) 
%#SORT_LINEAR_INDEX Just like SORT, but returns linear indices 

    sizeA = size(A); %# Get the matrix size 
    if nargin < 2 
    sortDim = find(sizeA > 1,1); %# Define sortDim, if necessary 
    end 
    if nargin < 3 
    sortOrder = 'ascend'; %# Define sortOrder, if necessary 
    end 
    [sortedA,sortIndex] = sort(A,sortDim,sortOrder); %# Sort the matrix 
    [subIndex{1:numel(sizeA)}] = ... %# Create a set of matrix subscripts 
    ind2sub(sizeA,reshape(1:prod(sizeA),sizeA)); 
    subIndex{sortDim} = sortIndex; %# Overwrite part of the subscripts with 
            %# the sort indices 
    sortIndex = sub2ind(sizeA,subIndex{:}); %# Find the linear indices 

end 

而現在我們可以測試出功能:

>> A = rand(1,10); 
>> [B,IX] = sort_linear_index(A); %# Sort a row vector 
>> isequal(B,A(IX)) 
ans = 
    1 
>> A = rand(3,4,3); 
>> [B,IX] = sort_linear_index(A,1); %# Sort a 3-by-4-by-3 matrix along 
>> isequal(B,A(IX))     %# the first dimension 
ans = 
    1 
>> [B,IX] = sort_linear_index(A,3); %# Sort a 3-by-4-by-3 matrix along 
>> isequal(B,A(IX))     %# the third dimension 
ans = 
    1 
>> [B,IX] = sort_linear_index(A,2,'descend'); %# Sort a 3-by-4-by-3 matrix along 
>> isequal(B,A(IX))       %# the second dimension 
ans =           %# in descending order 
    1 
+0

精彩---謝謝隊友! – Wajih 2017-01-05 10:11:59