Preserving the shape of the indices vector when indexing into another vector.
Show older comments
Suppose i have a vector of values A
A = [5 10 15 20 25];
And a vector of indeces that may have any number of singleton leading dimensions, e.g.
idx = zeros(1,1,3);
idx(:) = 1:3
idx(:,:,1) =
1
idx(:,:,2) =
2
idx(:,:,3) =
I want to get the elements of A specified by the subscripts in idx, and I want the output B to have the same dimensions as idx. In this example, what I want to get is
B(:,:,1) =
5
B(:,:,2) =
10
B(:,:,3) =
15
Instead of the default indexing behaviour which would get me:
B = A(idx)
B =
5 10 15
I know that i could obtain this by first initializing B to have the same size of idx, i.e.
B = zeros(size(idx));
B(:) = A(idx);
However, in my application, I am developing a toolbox that must be able to work with user-created functions. I can act on idx, which will be fed as an input to the user-created function, but the rest is up to the user and I cannot expect him to write these two lines of code.
Is there any way to achieve this?
4 Comments
Bruno Luong
on 16 Oct 2020
Edited: Bruno Luong
on 16 Oct 2020
I'm awared that for a vector A and idx
A(idx)
returns the vector having the same orientation than A.
Obviously your example shows this is also true for idx that is not only vector but "generalized" vector, meaning all dimensions are singleton excepted one*.
Not sure the behavious is documented.
I must admit this also surprises me. Exception rule like this is a source of buggy codes.
(*in all other cases the result has the same size as idx)
Stephen23
on 16 Oct 2020
The special case behavior for indexing vectors with vectors is documented here:
"When both A and B are vectors, the number of elements in C is the number of elements in B and with orientation of A."
There is no restriction on the orientation of either vector.
Bruno Luong
on 16 Oct 2020
Yeah but not a word about "generalized" vector as with Federico's example. And documented on a blog is kind of light evidence.
Federico Miretti
on 21 Oct 2020
Answers (1)
Ameer Hamza
on 16 Oct 2020
Edited: Ameer Hamza
on 16 Oct 2020
This can be one of the way
B = reshape(A(idx), size(idx));
Although, I wonder is why MATLAB does not follow normal behavior for indexing A(idx). Maybe there is a good reason, or maybe this is an oversight.
4 Comments
Federico Miretti
on 21 Oct 2020
Ameer Hamza
on 21 Oct 2020
Edited: Ameer Hamza
on 21 Oct 2020
As Stephen mentioned in his comment, this is intended behavior, modifying it will require changing MATLAB.
Are you able to control how matrix A is created? If yes, you can create a subclass of double data type and overload subsref(). For example, define a class like this
classdef myDouble < double
methods
function obj = myDouble(data)
if nargin == 0
data = 0;
end
obj = obj@double(data);
end
function B = subsref(A, S)
if strcmp(S.type, '()')
idx = S.subs{1};
B = reshape(builtin('subsref', A, S), size(idx));
else
fprintf('Indexing %s is not supported.\n', S.type);
B = NaN;
end
end
end
end
The define A like this
A = myDouble([5 10 15 20 25])
The rest will work as you want
idx = zeros(1,1,3);
idx(:) = 1:3;
Result
>> A(idx)
ans =
1×1×3 myDouble:
double data:
(:,:,1) =
5
(:,:,2) =
10
(:,:,3) =
15
Federico Miretti
on 22 Oct 2020
Edited: Federico Miretti
on 22 Oct 2020
Ameer Hamza
on 22 Oct 2020
Edited: Ameer Hamza
on 22 Oct 2020
I don't think that overloading subsindex will help here. subsindex only returns the indexes, but as we already saw, the shape of indexes have no effect on the output of indexing when idx is 1x1x3.
Categories
Find more on Multidimensional Arrays in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!