如何对单元格的元素进行排序? [英] How can I sort the elements of a cell?

查看:85
本文介绍了如何对单元格的元素进行排序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个像这样的牢房:

I have a cell like this:

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.

换句话说,此单元格每个元素中的列数是不同的,没有确定的模式.

In other words, the number of columns in each element of this cell is different, with no definite pattern.

现在,我想基于第一列中的元素对这些元素进行排序.我的意思是,我希望结果是这样的:

Now, I want to sort these elements based on the element at the first column. I mean, I want the result to be like this:

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循环部分非常慢.
我读过有关cat函数的信息,但我不知道如何使用它.我使用了B = cat(1,A{:}(1,1));,但出现此错误:??? Bad cell reference operation.

It works, but it takes much time. In fact the for loop part is very slow.
I read about cat function, but I don't know how to use it. I used B = cat(1,A{:}(1,1));, but there is this error: ??? Bad cell reference operation.

我想知道是否有更快的方法?

谢谢.

更新 让我们做一个实验:

Update Lets do an experiment:

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

and the result is
sum1=2.53635923001387
sum2=0.629729057743372
sum3=4.54007401778717
sum4=0.571285037623497

**这意味着按分配更快,但是第4种方法是什么.我认为值得在一个单独的问题中进行讨论.参见 Matlab预分配与否分配,第二个更快,为什么?

** Which means per-allocation is faster, but what is the 4-th method. I thought it deserves to be discussed in a separate question. see Matlab Pre-allocation vs. no allocation, the second one is faster, why?

推荐答案

您的循环很慢,因为B在其中生长;您应该为B预先分配内存,并且它应该运行得更快.为此,请在for循环之前插入以下行:

Your loop is slow because B is growing inside it; you should preallocate memory for B and it should run significantly faster. To do this, insert the following line before the for loop:

B = zeros(nrows, 1);

您可以像这样进一步缩短循环时间:

You can further shorten your loop like so:

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的较短解决方案(我之前提出)进行比较:

EDIT

I decided to compare this solution with a shorter solution that employs cellfun (which I formerly proposed):

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循环.

The loop runs by an order of magnitude faster than cellfun! This difference can be extremely noticeable for large arrays, so I recommend using a for loop in this problem.

这篇关于如何对单元格的元素进行排序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆