如何将{1xN}单元阵列的{Mx1}单元阵列转换为{Mx1单元}阵列的{1xN}单元阵列?

时间:2014-02-17 17:13:39

标签: matlab cell-array

假设C是一个形状为 M ×1的单元格数组(即size(C)返回[ M 1]),并且C的每个元素又是一个形状为1× N 的单元格数组。

我经常想将这样的单元格数组转换为形状为1× N 的新单元格数组D,元素为形状 M 的单元格数组×1,并且C{i}{j}等于D{j}{i}对于所有0&lt; i M ,并且0 < ĴÑ

我对此

使用以下怪物
D = arrayfun(@(j) arrayfun(@(i) C{i}{j}, (1:M)', 'un', 0), 1:N, 'un', 0);

但是这个操作的需要经常出现(毕竟,它是一种“单元阵列转置”),我想我会问:

  

有更标准的方法来执行此操作吗?

请注意,所需的D

不同
E = cat(2, C{:});

或等同地

E = cat(1, D{:});

上面的E是一个二维( M × N )单元格数组,而CD都是是一维单元阵列的一维单元阵列。当然,将E转换回CD也是另一种经常需要的操作(这种事情永远不会以MATLAB结束),但我会留下它另一篇文章。


这个问题背后的动机远远超出了上述问题。事实证明,我的MATLAB代码的巨大部分,以及我的MATLAB编程时间和精力的更大部分,都致力于这个基本上没有效率的 em>将数据从一种格式转换为另一种格式的繁琐工作。当然,在进行任何类型的计算工作时,格式转换是不可避免的,但是使用MATLAB,我发现自己做得更多,或者至少不得不比我工作时更加努力在其他系统中(例如, Mathematica 或Python / NumPy)。我希望通过构建我的MATLAB“格式转换技巧”,我将能够将我必须投入格式转换的MATLAB编程时间的一小部分降低到更合理的水平。


P.S。以下代码构造了一个C,如上所述,对于 M = 5和 N = 2。

uc = ['A':'Z'];
randstr = @() uc(randi(26, [1 4]));
M = 5;
rng(0);  % keep example reproducible
C = arrayfun(@(i) {randstr() i}, 1:M, 'un', 0)';

% C = 
%     {1x2 cell}
%     {1x2 cell}
%     {1x2 cell}
%     {1x2 cell}
%     {1x2 cell}
% >> cat(1, C{:});
% ans = 
%     'VXDX'    [1]
%     'QCHO'    [2]
%     'YZEZ'    [3]
%     'YMUD'    [4]
%     'KXUY'    [5]
%     

N = 2;
D = arrayfun(@(j) arrayfun(@(i) C{i}{j}, (1:M)', 'un', 0), 1:N, 'un', 0);

% D = 
%     {5x1 cell}    {5x1 cell}

1 个答案:

答案 0 :(得分:3)

这是使用num2cell的一个小技巧,它实际上适用于单元格数组输入 - 关键是首先将C扩展为5 x 2单元格数组(相当于cell(5,2) )。

% Your example to produce C
uc = ['A':'Z'];
randstr = @() uc(randi(26, [1 4]));
M = 5;
rng(0);  % Keep example reproducible
C = arrayfun(@(i) {randstr() i}, 1:M, 'un', 0)';

% D = num2cell(reshape([C{:}],[N M]).',[1 M])
D = num2cell(reshape([C{:}],[size(C{1},2) size(C,1)]).',[1 size(C,1)])

或更简单

D = num2cell(cat(1,C{:}),1)

D{:}返回的地方:

ans = 

    'VXDX'
    'QCHO'
    'YZEZ'
    'YMUD'
    'KXUY'


ans = 

    [1]
    [2]
    [3]
    [4]
    [5]

D返回C的逆操作可以通过以下方式完成:

% C = num2cell(reshape([D{:}],[N M]),[M N])
C = num2cell(reshape([D{:}],[size(D{1},1) size(D,2)]),[size(D,2) size(D{1},1)])

C = num2cell(cat(2,D{:}),2)

因此,您可以创建一个类似于以下任何方向的函数:

transpose_cells = @(C)num2cell(cat(isrow(C)+1,C{:}),isrow(C)+1);
isequal(transpose_cells(transpose_cells(C)),C)