error message"Matrix index is out of range for deletion."
26 views (last 30 days)
Show older comments
Mojgan Soltan
on 28 Mar 2020
Commented: Walter Roberson
on 30 Mar 2020
Hello,
I get this error message when I run my program. I will be grateful if helping me to fix this issue
I have attached the code.
3 Comments
Accepted Answer
Walter Roberson
on 28 Mar 2020
Consider: vector V = [1 2 -3 -4 5] . Task: delete negative elements.
for K = 1 : length(V)
if V(K) < 0;
V(K) = [];
end
end
Now
V(1) = 1 > 0 so leave V(1) alone. V = [[1] 2 -3 -4 5]
V(2) = 2 > 0 so leave V(2) alone. V = [1 [2] -3 -4 5]
V(3) = -3 < 0 so delete V(3). V = [1 2 [] -4 5]
V(4) = 5 > 0 so leave V(4) alone. V = [1 2 -4 [5]]
V(5) does not exist so fail with V = [1 2 -4 5]
Why did you fail? Because after you removed an element from V, V was no longer as long as it used to be, and for only evaluates its boundaries once, not every time through the loop, so length(V) the first time was copied into internal memory and length(V) is not re-calculated when V changes.
Why is -4 still there? Because when you deleted element 3, the elements after that "fell down" to occupy the empty slot, so the -4 moved into the place the -3 was, and the algorithm never re-examines a slot it already examined.
How can you get around this problem? There are several different ways:
- you can construct a vector indicating which elements you will need to delete, and then afterwards do a single deletion. For example, K = find(V<0); V(K) = [];
- you can use a while loop moving forward, because while does re-examine the values of the boundaries. When you delete an element, do not advance the index, so that next iteration you re-examine the same location you were just looking at (which is now filled with what used to be next in line)
- you can arrange so that you delete from back to front. This often works well.
6 Comments
Walter Roberson
on 30 Mar 2020
nnz = length ( As.VALUE ); % Number of nonzeros
for j = 1:nnz
so j will run up to the number of As.VALUE entries.
As.FIR ( j ) = [ ]; % Remove FIR row
You expect to delete one entry for each j value, so this assumes that FIR has at least as many entries as there are VALUE entries, but that is not at all true.
for j = 1:length ( As.FIR ) % Loop over FIR length
for k = 1:length ( As.VALUE ) % Loop over nonzero element
if ( As.NROW ( k ) == j && next_FIR == true ) % Find position
As.FIR ( j ) = As.POS ( k ); % Update FIR
next_FIR = false; % Update variable
end
and then you overwrite some FIR entries, leaving the others untouched??
Although your code has in-line comments about the mechanics of individual lines, you are short on documentation about what the purpose of the code is (and why you would want to do it), so I have no idea at the moment what you should be doing with the FIR entries.
As.POS ( k ) = [ ]; % Remove position
As.NROW ( k ) = [ ]; % Remove row
As.NCOL ( k ) = [ ]; % Remove column
As.VALUE ( k ) = [ ]; % Remove value
As.NIR ( k ) = [ ]; % Remove NIR
As.NIC ( k ) = [ ]; % Remove NIC
I have to wonder whether it would make more sense to use a non-scalar struct array As.NI, so that you could do something like
As.NI(k) = [];
where As.NI is a struct with (scalar) fields POS NROW NCOL VALUE NIR NIC.
Or perhaps it would make sense to use a table As.NIT with those variables, in which case
As.NIT(k,:) = [];
More Answers (0)
See Also
Categories
Find more on Matrix Indexing 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!