How to programmatically select which array dimension to address

22 次查看(过去 30 天)
I've run across this issue a few times, and I'm wondering if there's an elegant way to handle it.
Say I have a function that reorders the vectors/pages/etc of an N-D array along a specified dimension, but we don't really know how many dimensions this arbitrary array might have. How can I address the elements of the array? I can think of two solutions, neither of which seem particularly ideal.
On one hand, I could presume a maximum number of dimensions and just handle it with explicit cases. It wouldn't take that many cases to cover most practical scenarios. Let's say I presume a maximum of 5-D:
function outpict=reorderarray(myarray,whichdim)
sz=size(myarray);
reorderedVector=randi(sz(whichdim),[1 sz(whichdim)]);
switch whichdim
case 1
outpict=myarray(reorderedVector,:,:,:,:);
case 2
outpict=myarray(:,reorderedVector,:,:,:);
case 3
outpict=myarray(:,:,reorderedVector,:,:);
case 4
outpict=myarray(:,:,:,reorderedVector,:);
case 5
outpict=myarray(:,:,:,:,reorderedVector);
% we could go on ...
end
end
Alternatively, I could build the expression as a character array and use eval(). This seems like something I should avoid.
Is there a better way to do something like this?
  2 个评论
DGM
DGM 2021-3-16
Oof. I admit, I had struggled to find a good search query and could've done a better job. Thank you.

请先登录,再进行评论。

采纳的回答

Walter Roberson
Walter Roberson 2021-3-16
img = imread('flamingos.jpg');
imshow(reorderarray(img, 2));
imshow(reorderarray(img, 3));
imshow(reorderarray(img, 7));
function outpict = reorderarray(myarray,whichdim)
sz = size(myarray);
sz(end+1:whichdim) = 1; %in case asked for a dimension past the typical
idx = repmat({':'}, 1, length(sz));
idx{whichdim} = randperm(sz(whichdim));
outpict = myarray(idx{:});
end
  1 个评论
DGM
DGM 2021-3-16
Auugh! It works!
I had run across a similar example in a very old book, but in the printing, the curly braces were parentheses. I just figured it was some old syntax that no longer worked. I didn't even think that of course it would be a cell array. I should've been paying attention.
Many thanks to you, Stephen, and John.

请先登录,再进行评论。

更多回答(1 个)

John Chilleri
John Chilleri 2021-3-15
编辑:John Chilleri 2021-3-15
Hello,
I wouldn't suggest this to be an elegant solution, but it has worked so far for a number of test cases.
% A is myarray
% wdim is whichdim
% ordering is reorderedVector
function C = reorderarray(A,wdim,ordering)
sz = size(A); % Acquire size
pA = 1:length(sz); % Create permutation vector
pA(1) = wdim; % Swap desired dimension with first dimension
pA(wdim) = 1;
sz2 = sz; % Track permuted size
sz2(1) = sz(wdim);
sz2(wdim) = sz(1);
B1 = permute(A,pA); % Permute matrix so desired dimension is first
B2 = B1(ordering,:); % Reorder rows and restructure as 2D array
B3 = reshape(B2,sz2); % Reshape back into original permuted shape
C = permute(B3,pA); % Undo the permutation
end
I'll note that the process makes sense intuitively, but I wouldn't guarantee its correctness. The reshape restoring order seems to work because MATLAB has consistent methods of indexing across functions.
Thanks!
  1 个评论
DGM
DGM 2021-3-16
That works, but in my tests, it performs poorly in terms of execution time -- especially as array size increases. For a sample 100x10x10x10x10 array, it requires more than twice the time compared to the methods I described, and doubling the array size quintuples the time, whereas it only doubles it for the aforementioned methods.
I was actually surprised that the eval() method is actually slightly the fastest of the three. I've had it drilled into my head to avoid using eval(), but I'm not sure if this isn't a good use for it.

请先登录,再进行评论。

类别

Help CenterFile Exchange 中查找有关 Matrix Indexing 的更多信息

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by