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

kjo*_*kjo 10 matlab cell-array

假设它C是具有形状M  ×1 的单元阵列(即,size(C)返回[ M  1]),并且每个元素C又是具有形状1× N的单元阵列  .

我经常要这样的单元阵列转换到新的单元阵列D具有形状1×  Ñ,与元件是单元阵列具有形状中号  ×1,并且使得C{i}{j}等于D{j}{i}对于所有0 <   ≤  中号,和0 <  Ĵ  ≤  Ñ.

我为此使用了以下怪物

D = arrayfun(@(j) arrayfun(@(i) C{i}{j}, (1:M)', 'un', 0), 1:N, 'un', 0);
Run Code Online (Sandbox Code Playgroud)

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

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

请注意,所需D的不同

E = cat(2, C{:});
Run Code Online (Sandbox Code Playgroud)

或者,等效地,

E = cat(1, D{:});
Run Code Online (Sandbox Code Playgroud)

E上面是一个二维(中号  ×  Ñ)单元阵列,而这两个CD是一维单元阵列的一维单元阵列.当然,转换E回任何一个C或者D也是另一个经常需要的操作(这种事情永远不会用MATLAB结束),但我会把它留给另一个帖子.


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


PS以下代码构造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}
Run Code Online (Sandbox Code Playgroud)

hor*_*ler 3

这里有一个使用 的小技巧num2cell,它实际上适用于元胞数组输入 \xe2\x80\x93 ,关键是首先扩展C到 5×2 元胞数组(相当于cell(5,2))。

\n\n
% Your example to produce C\nuc = [\'A\':\'Z\'];\nrandstr = @() uc(randi(26, [1 4]));\nM = 5;\nrng(0);  % Keep example reproducible\nC = arrayfun(@(i) {randstr() i}, 1:M, \'un\', 0)\';\n\n% D = num2cell(reshape([C{:}],[N M]).\',[1 M])\nD = num2cell(reshape([C{:}],[size(C{1},2) size(C,1)]).\',[1 size(C,1)])\n
Run Code Online (Sandbox Code Playgroud)\n\n

或者更简单地说

\n\n
D = num2cell(cat(1,C{:}),1)\n
Run Code Online (Sandbox Code Playgroud)\n\n

在哪里D{:}返回:

\n\n
ans = \n\n    \'VXDX\'\n    \'QCHO\'\n    \'YZEZ\'\n    \'YMUD\'\n    \'KXUY\'\n\n\nans = \n\n    [1]\n    [2]\n    [3]\n    [4]\n    [5]\n
Run Code Online (Sandbox Code Playgroud)\n\n

D从后到的逆运算C可以通过以下方式完成:

\n\n
% C = num2cell(reshape([D{:}],[N M]),[M N])\nC = num2cell(reshape([D{:}],[size(D{1},1) size(D,2)]),[size(D,2) size(D{1},1)])\n
Run Code Online (Sandbox Code Playgroud)\n\n

或者

\n\n
C = num2cell(cat(2,D{:}),2)\n
Run Code Online (Sandbox Code Playgroud)\n\n

因此,您也许能够创建一个如下所示的函数,该函数可以在任一方向上工作:

\n\n
transpose_cells = @(C)num2cell(cat(isrow(C)+1,C{:}),isrow(C)+1);\nisequal(transpose_cells(transpose_cells(C)),C)\n
Run Code Online (Sandbox Code Playgroud)\n