如何将小型n-d阵列组装成更大的n-d阵列?

时间:2014-01-27 22:21:42

标签: matlab

下面的代码生成一个包含 n (= 210)2x3x4形n-d数组的单元格数组。

n = prod(5:7);
makendarray = @(i) reshape(1:24, 2:4) + (i * 1000);
ndarrays = cellfun(makendarray, num2cell(1:n), 'un', 0);

对于每个 i ∈{1,..., n }, i -th nd数组的内容都是其初始的整数数字与 i 的数字匹配。例如,对于 i = 123:

>> ndarrays{123}

ans(:,:,1) =

      123001      123003      123005
      123002      123004      123006


ans(:,:,2) =

      123007      123009      123011
      123008      123010      123012


ans(:,:,3) =

      123013      123015      123017
      123014      123016      123018


ans(:,:,4) =

      123019      123021      123023
      123020      123022      123024

我希望将所有这些nd数组组装成一个更大的[5x6x7x2x3x4 double] nd数组X,使得X(i,j,k,:,:,:)形式的表达式对应于原始的较小nd数组之一。最后一个要求是给我带来困难的要求。

从较小的数组生成较大的[5x6x7x2x3x4 double] n-d数组没有问题,但X(i,j,k,:,:,:)形式的表达式不会产生原始的较小n-d数组。

下面是我尝试过的一件事的例子;下面应该匹配的最后一个输出应该与上面ndarrays{123}显示的输出匹配,但不匹配:

>> X = reshape(cell2mat(ndarrays), [5:7 2:4]);
>> [idx{1:3}] = ind2sub(5:7, 123);
>> squeeze(X(idx{:}, :, :, :))

ans(:,:,1) =

       62001       62003       62005
      167001      167003      167005


ans(:,:,2) =

       62007       62009       62011
      167007      167009      167011


ans(:,:,3) =

       62013       62015       62017
      167013      167015      167017


ans(:,:,4) =

       62019       62021       62023
      167019      167021      167023

编辑:好的,通过(几乎是盲目的)试错法我发现以下方法可以解决问题:

tmp = cellfun(@(c) reshape(c, [1 24]), ndarrays, 'un', 0);
X = reshape(cat(1, tmp{:}), [5:7 2:4]);

IOW:在将子数组传递给cat(1, ...)之前将其线性化。我很惊讶有必要明确地执行这个线性化步骤:这是我期望MATLAB默认执行的操作(例如,在cell2mat中)。

尽管如此,是否有更好(或至少更清晰/更容易理解)的方式来达到同样的效果?

(顺便说一句,对于这个问题,ndarray的初始形状是给定的,不会发生变化。现在,需要修改示例中的makesubarray函数的解决方案不符合我的情况。处理。)

EDIT2:在参考Luis Mendo的回答时,这是一个小脚本(带echo on)的输出(从我的MATLAB工作区逐字复制粘贴),显示各种大小项目:

n = prod(5:7);
makendarray = @(i) reshape(1:24, 2:4) + (i * 1000);
ndarrays = cellfun(makendarray, num2cell(1:n), 'un', 0);
size(ndarrays)

ans =

     1   210

size(permute(ndarrays, [2 3 4 1]))

ans =

   210     1

size(cell2mat(permute(ndarrays, [2 3 4 1])))

ans =

   420     3     4

echo off;

1 个答案:

答案 0 :(得分:1)

您只需permutereshape即可实现。这种方法的逻辑可以在每个步骤结束时观察size(X)(在评论中指出):

X = cell2mat(permute(ndarrays(:), [2 3 4 1])); %// size [2 3 4 210]
X = permute(X, [4 5 6 1 2 3]); %// size [210  1  1  2  3  4]
X = reshape(X, [7 6 5 2 3 4]); %// size [7  6  5  2  3  4]
X = permute(X, [3 2 1 4 5 6]); %// size [5  6  7  2  3  4]