未知维矩阵的索引

Gun*_*uyf 10 matlab multidimensional-array matrix-indexing

我有一个非固定的维矩阵M,我想从中获取单个元素.元素的索引包含在向量J.中.

例如:

M = rand(6,4,8,2);
J = [5 2 7 1];

output = M(5,2,7,1)
Run Code Online (Sandbox Code Playgroud)

这次M有4个维度,但事先并不知道.这取决于我正在编写的算法的设置.它也可能是这样

M = rand(6,4);
J = [3 1];

output = M(3,1)
Run Code Online (Sandbox Code Playgroud)

所以我不能简单地使用

output=M(J(1),J(2))
Run Code Online (Sandbox Code Playgroud)

我正在考虑使用sub2ind,但这也需要它的变量逗号分隔..

@gnovice

这是有效的,但我打算从矩阵中使用这种元素提取M相当多.因此,如果我cellJ每次访问时都必须创建一个临时变量M,这不会极大地减慢计算速度吗?

我也可以写一个单独的函数

function x= getM(M,J)
    x=M(J(1),J(2));
    % M doesn't change in this function, so no mem copy needed = passed by reference
end
Run Code Online (Sandbox Code Playgroud)

并根据算法的不同配置进行调整.这当然是速度与灵活性的考虑因素,我没有将其纳入我的问题中.

但是:这仅仅是可用于获得元件,用于设置有没有其他的方法比实际使用的索引(并且优选线性索引).我仍然认为sub2ind是一个选项.我想要的最终结果是:

function idx = getLinearIdx(J, size_M)
    idx = ...
end
Run Code Online (Sandbox Code Playgroud)

结果:

function lin_idx = Lidx_ml( J, M )%#eml
%LIDX_ML converts an array of indices J for a multidimensional array M to
%linear indices, directly useable on M
%
% INPUT
%   J       NxP matrix containing P sets of N indices
%   M       A example matrix, with same size as on which the indices in J
%           will be applicable.
%
% OUTPUT
%   lin_idx Px1 array of linear indices
%

% method 1
%lin_idx = zeros(size(J,2),1);
%for ii = 1:size(J,2)
%    cellJ = num2cell(J(:,ii)); 
%    lin_idx(ii) = sub2ind(size(M),cellJ{:}); 
%end

% method 2
sizeM = size(M);
J(2:end,:) = J(2:end,:)-1;
lin_idx = cumprod([1 sizeM(1:end-1)])*J;

end
Run Code Online (Sandbox Code Playgroud)

方法2为20(少量的索引集(=P)转换)到80(大量的索引集(=P))倍方法1.容易的选择快

gno*_*ice 12

对于J可以是任何长度的一般情况(我假设它总是匹配维度的数量M),你有几个选项:

  1. 您可以J使用NUM2CELL函数将每个条目放在单元格数组的单元格中,然后使用冒号运算符从此单元格数组创建逗号分隔列表:

    cellJ = num2cell(J);
    output = M(cellJ{:});
    
    Run Code Online (Sandbox Code Playgroud)
  2. 您可以回避SUB2IND函数并通过一些数学计算自己计算线性索引:

    sizeM = size(M);
    index = cumprod([1 sizeM(1:end-1)]) * (J(:) - [0; ones(numel(J)-1, 1)]);
    output = M(index);
    
    Run Code Online (Sandbox Code Playgroud)

  • @GuntherStruyf:您可以做的最好的事情是使用MATLAB Profiler来确定花费最多时间的地方并对其进行优化.数组索引可能只是运行时的0.1%.即使你完全神奇地消除了这个成本,你的总运行时间也会减少...... 30秒.另一方面,使用MATLAB内置函数(用C语言编写)尽可能地对所有内容进行矢量化,在开始循环之前预先分配数组 - 这些都可以提高性能. (4认同)