【问题标题】:Fast way to create cell array or 3D-Matrix without for loop无需 for 循环即可创建单元阵列或 3D 矩阵的快速方法
【发布时间】:2016-08-25 11:29:07
【问题描述】:

我有一个列向量和一个行向量。

a = [1;2;3]
b = [10 20 30 40 50 60 70 80 90]

我希望将b 切成[10 20 30]、[40 50 60]、[70 80 90] 并创建一个元胞数组 C 这样

C{1} = a*[10 20 30]
C{2} = a*[40 50 60]
C{3} = a*[70 80 90]

没有 for 循环。这在 MATLAB 中是如何实现的?

我也希望有

a = [1;2;3]
b = [10 20 30 40 50 60 70 80 90 100 110 120]

这样

C{1} = a*[10 20 30]
C{2} = a*[40 50 60]
C{3} = a*[70 80 90]
C{4} = a*[100 110 120]

附:如果这不可能,如何创建一个 3 维数组 D 使得

D(:,:,1) = a*[10 20 30]
D(:,:,2) = a*[40 50 60]
D(:,:,3) = a*[70 80 90]

没有for循环?

我也希望有

a = [1;2;3]
b = [10 20 30 40 50 60 70 80 90 100 110 120]

这样

D(:,:,1) = a*[10 20 30]
D(:,:,2) = a*[40 50 60]
D(:,:,3) = a*[70 80 90]
D(:,:,4) = a*[100 110 120]

【问题讨论】:

    标签: arrays matlab vectorization


    【解决方案1】:

    在性能方面,3D 矩阵肯定是比单元阵列更好的选择!首先,您可以使用permute 将a 转换为第三维和reshape 以获得所需的矩阵基本形状(根据您的实际情况进行编辑)。最后你需要bsxfun 来执行实际的乘法运算。

    n = 3;
    a = [1;2;3]
    b = [10 20 30 40 50 60 70 80 90 100 110 120]
    
    %// permuting a to 3rd dimension
    A = permute(a,[2,3,1])
    %// reshaping b
    B = reshape(b.', [], n)
    
    %// multiplication and forming of 3D-array
    out = bsxfun(@mtimes,B,A)
    

    out(:,:,1) =
    
        10    50    90
        20    60   100
        30    70   110
        40    80   120
    
    
    out(:,:,2) =
    
        20   100   180
        40   120   200
        60   140   220
        80   160   240
    
    
    out(:,:,3) =
    
        30   150   270
        60   180   300
        90   210   330
       120   240   360
    

    替代解决方案,取决于解释:

    %// reshaping and permuting b
    B = permute(reshape(b.', n, []),[3,1,2])
    
    %// multiplication and forming of 3D-array
    out = bsxfun(@mtimes,B,a)
    

    out(:,:,1) =
    
        10    20    30
        20    40    60
        30    60    90
    
    
    out(:,:,2) =
    
        40    50    60
        80   100   120
       120   150   180
    
    
    out(:,:,3) =
    
        70    80    90
       140   160   180
       210   240   270
    
    
    out(:,:,4) =
    
       100   110   120
       200   220   240
       300   330   360
    

    【讨论】:

    • 谢谢,实际上我也希望它适用于具有复数条目的数组。应该怎么改?
    • 完全没有,它完全兼容复数。
    • 哦,谢谢。如果b = [10 20 30 40 50 60 70 80 90] 不能重新整形为方阵怎么办?例如,b = [10 20 30 40 50 60 70 80 90 100 110 120]?
    • 实际上如果b = [10 20 30 40 50 60 70 80 90 100 110 120]。我希望D(:,:,1) = a*[10 20 30]、D(:,:,2) = a*[40 50 60]、D(:,:,3) = a*[70 80 90]、D(:,:,4) = a*[100 110 120]。我该怎么做?
    • @kww 好吧,是的。 -> permute(reshape(b.', n, []),[3,1,2]) -> 查看编辑
    【解决方案2】:

    正如the other answer 中所述,使用 3 维肯定会给您带来更好的性能。但是,由于问题是关于单元格的,我将提供一些技巧如何使用单元格来处理这个问题。

    a = [1;2;3]; % userdata
    b = [10 20 30 40 50 60 70 80 90,100,110,120]; % userdata
    B = reshape(b,length(b)/3,3).'; % reshape b to 3-by-3 matrix and transpose
    carr = mat2cell(B,[1,1,1],3); % split each row to a cell
    res = cellfun(@(x) mtimes(a,x) ,carr, 'un',0); % for every cell multiplicate with a
    

    所以更喜欢 3D 矩阵,但如果你想要单元格,就是这样。

    编辑

    对于包含 b×3 矩阵的任意数量的单元格,可以使用以下内容。

    a = [1;2;3];
    b = [10 20 30 40 50 60 70 80 90,100,110,120];
    ncells = length(b)/3;
    B = reshape(b,3,ncells).';
    carr = mat2cell(B,ones(1,ncells),3);
    res = cellfun(@(x) mtimes(a,x) ,carr, 'un',0);
    res{:}
    

    建议您使用debugger 逐步执行代码并研究reshape 和mat2cell 的工作原理。这将使您可以根据需要自定义此代码。

    【讨论】:

    • 对于b = [10 20 30 40 50 60 70 80 90 100 110 120],你能告诉我如何获得C{1} = a*[10 20 30],C{2} = a*[40 50 60],C{3}= a*[70 80 90],C{4} = a*[100 110 120]吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多