Preserving the shape of the indices vector when indexing into another vector.

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

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)
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.
Yeah but not a word about "generalized" vector as with Federico's example. And documented on a blog is kind of light evidence.
Thank you all for your comments.
@Stephen Colbeck: I understand that that's the default behaviour for indexing vectors with vectors. My problem is, I need the exact opposite: I need the number of elements of C to be the number of elements in B with the orientation of B.
I know this may not be possible at all, but I still thought it was worth trying here on Answers.

Sign in to comment.

Answers (1)

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

Thank you for your answer. However, I cannot use this solution as the part of the code where B is assigned is not something I write myself, it is part of a user-defined function.
Since the user does not know the internal working of my program, he does not really know what the size of idx will be. Another way I can explain this is that the user will write his function assuming that idx is a scalar; so he will simply write B = A(idx) and assume that everything works just fine.
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
I cannot act on A, as A might be any vector defined by the user. The only thing I can act on is idx... Can I achieve what you are suggesting by defining a subclass fo idx? I saw on the documentation that there is a method called subsindex which seems relevant.
Do you think it could make sense to define a subclass for idx and overload subsindex? (I have no experience with overloading methods so I'm not really sure what I am talking about).
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.

Sign in to comment.

Categories

Asked:

on 16 Oct 2020

Edited:

on 22 Oct 2020

Community Treasure Hunt

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

Start Hunting!