假设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 )单元格数组,而C
和D
都是是一维单元阵列的一维单元阵列。当然,将E
转换回C
或D
也是另一种经常需要的操作(这种事情永远不会以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}
答案 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)