2011-06-17 58 views
6

我有一个d维数组,A和矢量inds长度等于d。我想访问的价值Ainds。理想情况下,我会做类似A(* inds)(借用Python的拆包语法)。我不知道如何在MATLAB中做到这一点。MATLAB:使用列表访问多维数组的元素

如果我做A(INDS)我实际上是从一个得到单独d值,这是不是我想要的。我想要的是inds的元素i是函数调用A()中的第i个参数。

+0

可能相关的问题:http://stackoverflow.com/questions/2337126/how-do-i-do-multiple-assignment-in-matlab(并链接到它的所有其他人) – Amro

回答

13

一种解决方案是从您的下标索引inds的矢量中创建一个comma-separated list。您可以通过使用NUM2CELL将其转换为一个单元阵列,然后使用{:}语法索引A当做到这一点:

inds = num2cell(inds); 
value = A(inds{:}); 
+0

辉煌!谢谢! – faken

+0

终于有办法在参数列表中解压矢量了...... –

0

我觉得这个工具可以帮助你:

如果你有一个ND矩阵如R = rand(5,10,15,20),并且要访问特定模式中的元素,则可以使用spindex以与输入访问相同的形状访问输出。所以如果你有size(i1)= [5,5,5],size(i2)= [5,5,5]等等,那么size(spindex(R,i1,i2,i3,i4))也等于[5,5,5]。

%#example: 

z = reshape(1:(5^4),[5,5,5,5]); 
zid1 = [1,1,5]; 
zid2 = [1,2,5]; 
zid3 = [1,3,5]; 
zid4 = [1,4,5]; 
zOut = spindex(z,zid1,zid2,zid3,zid4) 
%# should be like [1,431,625] 
zid1 = [1,2;3,4]; 
zid2 = [1,1;1,1]; 
zid3 = [1,1;1,1]; 
zid4 = [1,1;1,1]; 
zOut = spindex(z,zid1,zid2,zid3,zid4) 
%%# should be like [[1,2];[3,4]] 

您需要将以下代码作为spindex.m添加到您的MATLAB路径中的位置。

function outM = spindex(inM,varargin) 
%function outM = spindex(inM,varargin) 
% 
%returns a matrix indexed from inM via index variables contained in varargin 
%useful for retreiving multiple values from a large multidimensional matrix 
% 
% 
%inM is an N-d matrix 
%the index variables stored in varargin must be as numerous as the number of dimensions in inM 
%each index variable must be identical in size 
% 
%example: 
% 
%z = reshape(1:(5^4),[5,5,5,5]); 
%zid1 = [1,1,5]; 
%zid2 = [1,2,5]; 
%zid3 = [1,3,5]; 
%zid4 = [1,4,5]; 
%zOut = spindex(z,zid1,zid2,zid3,zid4) 
%% should be like [1,431,625] 
%zid1 = [1,2;3,4]; 
%zid2 = [1,1;1,1]; 
%zid3 = [1,1;1,1]; 
%zid4 = [1,1;1,1]; 
%zOut = spindex(z,zid1,zid2,zid3,zid4) 
%% should be like [[1,2];[3,4]] 
sz = size(inM); 
ndim = length(sz); 
if((ndim == 2) & (sz(2) ==1)) % ndim always returns at least 2 
    ndim =1; 
end 
if(nargin ~= (ndim +1)) 
    extraDims = setdiff(1:(nargin - 1),1:ndim); 
    for iExtraDim = extraDims 
     if(any(varargin{iExtraDim}~=1)) 
      error('must have as many indicies as dimensions\n'); 
     end 
    end 
end 
szid = size(varargin{1}); 
for i = 1:ndim 
    szid2 = size(varargin{i}); 
    if(any(szid2 ~= szid)) 
     error('indicies must have identical shape'); 
    end 
    ndIdxs(:,i) = varargin{i}(:); 
end 
if(ndim == 1) 
    idxs = ndIdxs(:,1); 
else 
    idxs = myNDsub2ind(size(inM),ndIdxs); 
end 
outM = nan(1,length(idxs)); 
outM(find(not(isnan(idxs)))) = inM(idxs(find(not(isnan(idxs))))); 
outM = reshape(outM,size(varargin{1})); 





function ndx = myNDsub2ind(siz,subs) 
%function ndx = NDsub2ind(siz,subs) 
%------------------------------- 
%works more smoothly when the dimensionality of the mtrx is unknown 
%siz should be like [10 10 4 5] if subs is like 
% 9 8 3 5 
% 1 1 1 1 
% 10 10 4 5 
% 5 8 3 3 
% 
% siz will be rotated for you if submit a row vec instead a col vector 
% example: NDsub2ind([10 10 4 5],[[9,8,3,5];[1,1,1,1]]) 
%---------------------------------------------- 
if(size(siz,1) > 1) && (size(siz,2) > 1) 
    error('the siz variable must be a vector'); 
end 

if((size(subs,1) ~= 1) && (size(subs,2) == 1)) 
    subs = subs'; 
end 
siz = siz(:)'; 
if length(siz)<2 
     error('MATLAB:sub2ind:InvalidSize',... 
      'Size vector must have at least 2 elements.'); 
end 

if ((length(siz) ~= size(subs,2))) 
    error('NDsub2ind: length(siz) must = size(subs,2)'); 
end 

nPoints = size(subs,1); 


%Compute linear indices 
k = [1 cumprod(siz(1:end-1))]; 
ndx = ones(nPoints,1); 
s = size(subs); %For size comparison 
for i = 1:length(siz), 
    v = subs; 
    fNaN = find( (v(:,i) < 1) | (v(:,i) > siz(i)) ); 
    %Verify subscripts are within range 
    v(fNaN,i) = nan; 
    ndx = ndx + (v(:,i)-1)*k(i); 
end