5

私はこのようなセルを持っています:

A{1,1}=[ 1 ;2; 3;];
A{2,1}=[ 4 ;2;];
A{3,1}=[ 3 ;2; 5; 4; 6;];
...
A{N,1}=[ 10 ;2;5; 7;];   %N is very large.

つまり、このセルの各要素の列数は異なり、明確なパターンはありません。

ここで、最初の列の要素に基づいてこれらの要素を並べ替えます。つまり、結果を次のようにしたいと思います。

Asorted{1,1}=[ 1 ;2; 3;];
Asorted{2,1}=[ 3 ;2; 5; 4; 6;];
Asorted{3,1}=[ 4 ;2;];
...
Asorted{N,1}=[ 10 ;2;5; 7;];

現在、私はこの関数を使用しています:

function Asorted = sortcell(A)
B=[];
nrows = size(A,1);

for i=1:nrows            % this for-loop is slow
    st=A{i,1};
    B(i,1) = st(1,1);
end
[sorted,indices] = sort(B);
Asorted = A(indices,:);
end 

動作しますが、時間がかかります。実際、forループ部分は非常に遅いです。
猫の機能について読んだのですが、使い方がわかりません。を使用B = cat(1,A{:}(1,1));しましたが、次のエラーがあります。??? Bad cell reference operation.

これを行うより速い方法があるかどうか知りたいですか?

ありがとう。

更新 実験をしましょう:

A={};
for i=1:1e3
    A{i,1} = ones(4,1) * randn;
end

N=1000;sum1=0;sum2=0;sum3=0;sum4=0;
for t=1:N

    % # Solution with for loop and no prealocation
    tic
    B = [];
    for i = 1:size(A, 1)
        B(i, 1) = A{i,1}(1,1);
    end
    [Y, I] = sort(B);
    Asorted = A(I,:);
    a=toc;sum1=sum1+a;

    % # Solution with for loop and Prealocation
    tic
    B = zeros(size(A,1), 1);
    for i = 1:size(A, 1)
        B(i, 1) = A{i,1}(1,1);
    end
    [Y, I] = sort(B);
    Asorted = A(I,:);
    a=toc;sum2=sum2+a;

    % # Solution with cellfun
    tic
    [Y, I] = sort( cellfun( @(x) x(1), A ) );
    Asorted = A(I);
    a=toc;sum3=sum3+a;
    tic

    % # Solution with for loop and ???
    for i = 1:size(A, 1)
        B(i, 1) = A{i}(1);
    end
    [Y, I] = sort(B);
    Asorted = A(I);
    a=toc;sum4=sum4+a;
end

結果は
sum1=2.53635923001387
sum2 = 0.629729057743372
sum3 = 4.54007401778717
sum4 = 0.571285037623497

**これは、割り当てごとの方が高速であることを意味しますが、4番目の方法は何ですか。別の質問で議論する価値があると思いました。Matlabの事前割り当てと割り当てなしを参照してください。2番目の方が高速です。なぜですか?

4

2 に答える 2

6

Bループは内部で成長しているため、ループは遅くなります。にメモリを事前に割り当てるB必要があり、実行速度が大幅に向上します。これを行うには、forループの前に次の行を挿入します。

B = zeros(nrows, 1);

次のように、ループをさらに短くすることができます。

B = zeros(size(A,1), 1);
for i = 1:size(A, 1)
    B(i, 1) = A{i}(1);
end
[Y, I] = sort(B);
Asorted = A(I);

編集

cellfun私はこのソリューションを、 (以前に提案した)を使用するより短いソリューションと比較することにしました。

A = {[1; 2; 3], [4; 2], [3; 2; 5; 4; 6], [10; 2; 5; 7]};

% # Solution with a for loop
tic
for jj = 1:1e3
    B = zeros(size(A,1), 1);
    for i = 1:size(A, 1)
        B(i, 1) = A{i}(1);
    end
    [Y, I] = sort(B);
    Asorted = A(I);
end
toc

% # Solution with cellfun
tic
for jj = 1:1e3
    [Y, I] = sort( cellfun( @(x) x(1), A ) );
    Asorted = A(I);
end
toc

結果は次のとおりです。

Elapsed time is 0.028761 seconds.
Elapsed time is 0.253888 seconds.

cellfunループは!よりも1桁速く実行されます。この違いは、大きなアレイでは非常に顕著になる可能性があるためfor、この問題ではループを使用することをお勧めします。

于 2012-12-24T12:15:26.427 に答える
3

使用できますcellfun

[~, I] = sort( cellfun( @(x) x(1), A ) );
Asorted = A(I);
于 2012-12-24T13:00:43.483 に答える