How Do Assignment and Deletion Work with an Empty Index on the Left Hand Side ?

42 visualizzazioni (ultimi 30 giorni)
I've always thought that indexing with an empty array on the LHS of an = is a no-op for the variable on the LHS (there could be side effects of the evaluation of the RHS).
For example
% Case 1
A = [1 2;3 4];
A([]) = 5
A = 2×2
1 2 3 4
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
But, assigning a non-scalar on the RHS result in an error
% Case 2
try
A([]) = [5,6];
catch ME
ME.message
end
ans = 'Unable to perform assignment because the left and right sides have a different number of elements.'
Why doesn't Case 1 result in an error insofar as it also had a different number of elements on the left and right sides?
Using the deletion operator on the RHS with an empty index on the LHS reshapes the matrix
% Case 3
A = [1 2;3 4];
A([]) = []
A = 1×4
1 3 2 4
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
Why does a request to delete nothing from A change A?
But that doesn't happen if A is column vector
% Case 4
A = [1;2;3;4];
A([]) = []
A = 4×1
1 2 3 4
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
Deletion with a non-zero dimension of an empty index also reshapes the LHS
% Case 5
A = [1 2;3 4];
A(double.empty(0,1)) = []
A = 1×4
1 3 2 4
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
A = [1 2; 3 4];
A(double.empty(1,0)) = []
A = 1×4
1 3 2 4
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
I suppose Cases 3 and 5 are related to deleting a specific (non-empty) element from a matrix
% Case 6
A = [1 2;3 4];
A(3) = []
A = 1×3
1 3 4
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
But I'm surprised that the result is not a column vector.
Are any/all of these results following a general rule? Pointers to relevant documentation would be welcome. I couldn't find any.
  2 Commenti
dpb
dpb il 23 Ago 2025 alle 14:14
Modificato: dpb il 23 Ago 2025 alle 15:00
Another set of corner cases without a public design document/standard to refer to.
On this one I don't think there's a word said anywhere in the doc.
Just out of curiosity, can you give an example of useful code that deliberately does a nul assignment?
I see cases in which a computed reference does expect a result but yields a nul instead in which case it is an error; I suppose the exercise could be seeing what the result of that might be? For comparison, my practice is to test the result for being empty first, not to rely on default behavior in cases where it is known that indeed, there may not be anything to satisfy the condition. Sometimes there's alternative action, sometimes its a do-nothing, sometimes it actually is an error, but have to handle each.
Paul
Paul il 23 Ago 2025 alle 16:20
I assume that Case 1 goes through w/o error because of a rule about scalar expansion of the RHS.
As for the other cases, I can only guess that Cases 3 and 5 work as they do to be consistent with Case 6. It appears the rule is that using an empty linear index to delete elements of an array that has more than one non-unity dimension returns a row vector.
If the array has only one (or none) non-unity and non-zero dimensions, then it's left unchanged as in Case 4, also for N-D
A = rand(1,1,2);
A([]) = [] % does not reshape to a row vector
A =
A(:,:,1) = 0.5770 A(:,:,2) = 0.1055
"can you give an example of useful code that deliberately does a nul assignment?"
If by null assignment you mean using a literal [] as the index on the LHS, then no.
BTW, the noted behavior only arises when the RHS is a literal deletion operator.
A = [2,2;3 4];
try
A(find(A==2)) = returnempty;
catch ME
ME.message
end
ans = 'Unable to perform assignment because the left and right sides have a different number of elements.'
That's actually a good thing because there should then be no way for something like
A = [1,2;3 4];
%A(f1(...)) = f2(...)
to silently reshape A even if f1 and f2 both return 0 x 0 results.
A(returnempty()) = returnempty()
A = 2×2
1 2 3 4
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
Indexing on the LHS of an assignment with an empty array might not be uncommon for those still using find instead of logical indexing, so left side indexing with an empty array might at least be worthy of a mention at Indexed Assignment
function r = returnempty()
r = [];
end

Accedi per commentare.

Risposta accettata

Stephen23
Stephen23 il 24 Ago 2025 alle 6:24
Modificato: Stephen23 il 24 Ago 2025 alle 6:51
"Why doesn't Case 1 result in an error insofar as it also had a different number of elements on the left and right sides?"
Case 1: Assigning a scalar is a special case: "...MATLAB supports scalar expansion, where it expands a single scalar value on the right side to replace multiple elements on the left." source: https://www.mathworks.com/help/matlab/math/indexed-assignment.html
However, the term "multiple" is misleading as scalar value is actually expanded to any number of elements, including zero elements. This is also consistent with how scalar dimension expansion works.
Case 2: Not a scalar so the above rule does not apply. The error message makes the problem clear.
Cases 3,5,6: A design decision. All single index indexing is linear indexing. Linear indexing used for deletion returns a row vector regardless of how many elements that index has:
Case 4: My guess is that this is related to the "...except for the special case where A and id are both vectors" rule for extracting a subarray out of an array: https://www.mathworks.com/help/matlab/math/detailed-rules-about-array-indexing.html (but strictly speaking in my mind a vector at-most one non-scalar dimension, which does not apply to [] which has two non-scalar dimensions).

Più risposte (0)

Categorie

Scopri di più su Resizing and Reshaping Matrices in Help Center e File Exchange

Prodotti


Release

R2025a

Community Treasure Hunt

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

Start Hunting!

Translated by