How to index one array by assigned vector in certain dimension

2 views (last 30 days)
Hi,
I'd like to form a new 2D array by indexing another 3D array, where the indexing is via one assigned vector.
Details like below:
Given arr_i,vec_i, want to find func_index as
arr_o = func_index(arr_i,vec_i);
%%%
arr_i1 = [111,112,113,114; ...
121,122,123,124];
arr_i2 = [211,212,213,214; ...
221,222,223,224];
arr_i3 = [311,312,313,314; ...
321,322,323,324];
arr_i = cat(3,arr_i1,arr_i2,arr_i3);
vec_i = [2,3,1,2];
arr_o = func_index(arr_i,vec_i);
%%%
With above operation, I expect arr_o will be
[211,312,113,214; ...
221,322,123,224];
The in/out relationship of func_index is:
arr_o(1:2,1) = arr_i(1:2,1,2), since vec_i(1) == 2;
arr_o(1:2,2) = arr_i(1:2,2,3), since vec_i(2) == 3;
arr_o(1:2,3) = arr_i(1:2,3,1), since vec_i(3) == 1;
arr_o(1:2,4) = arr_i(1:2,4,2), since vec_i(4) == 2;
Keypoint here is assigned vector actually index 3D array in certain one dimension (in this case is dim_3), and result in new 2D array.
Please propose matrix operation (avoiding loop, since the real array is quite big).
Thanks!!

Accepted Answer

DGM
DGM on 15 Jun 2021
There are probably multiple ways of doing this. It could probably be done with a bunch of reshaping and such, but I did it this way. I'm not sure which would be faster or less confusing.
arr_i1 = [111,112,113,114; ...
121,122,123,124];
arr_i2 = [211,212,213,214; ...
221,222,223,224];
arr_i3 = [311,312,313,314; ...
321,322,323,324];
arr_i = cat(3,arr_i1,arr_i2,arr_i3);
% [211,312,113,214;
% 221,322,123,224];
% calculate all 8 subscripts for each axis
xvec = repelem(1:4,2);
yvec = repmat(1:2,[1 4]);
zvec = repelem([2 3 1 2],2);
% convert to linear indices
idx = sub2ind(size(arr_i),yvec,xvec,zvec);
reshape(arr_i(idx),2,[])
ans = 2×4
211 312 113 214 221 322 123 224
Otherwise, trying to do something directly like
arr_i(:,1:4,[2 3 1 2])
Would give the intersection of the subscript ranges. Such a result would be a much larger set than intended, and the desired result would be its block diagonal.
  3 Comments
DGM
DGM on 15 Jun 2021
If you don't have repelem, you can probably just use kron()
x = 1:4
x = 1×4
1 2 3 4
repelem(x,2)
ans = 1×8
1 1 2 2 3 3 4 4
kron(x,[1 1])
ans = 1×8
1 1 2 2 3 3 4 4
Warren Chuo
Warren Chuo on 21 Jun 2021
Thank you for suggesting 'kron'.
I'll try this tensor formula later.

Sign in to comment.

More Answers (0)

Products


Release

R2010b

Community Treasure Hunt

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

Start Hunting!