How to programmatically select which array dimension to address

22 ビュー (過去 30 日間)
DGM
DGM 2021 年 3 月 15 日
コメント済み: DGM 2021 年 3 月 16 日
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 Center および File ExchangeMatrix Indexing についてさらに検索

Community Treasure Hunt

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

Start Hunting!

Translated by