我有一个这样的单元格:
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 Pre-allocation vs. no allocation, the second one is faster, why?
答案 0 :(得分: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
快一个数量级!对于大型数组,这种差异非常明显,因此我建议在此问题中使用for
循环。
答案 1 :(得分:3)
您可以使用cellfun
[~, I] = sort( cellfun( @(x) x(1), A ) );
Asorted = A(I);