2011-06-17 59 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