Clear Filters
Clear Filters

Looping through object array, possible to get an iterator to index into the object array?

64 views (last 30 days)
When looping through object arrays using the 'ranged base for loop', is there any way to get an 'iterator' without having to specifically make one elsewhere such that I can index into the object array? What I would like to do is:
for tmpObject = myObjectArray
if ...
myObjectArray(tmpObject) = []
but this produces the error (which makes sense as tmpObject is not an number)
Unable to use a value of type tmpObject as an index.
I've done this which works, but it just feels messy and seems to defeat the purpose of using the range based for loop:
i = 1;
for tmpObject = myObjectArray
if ...
myObjectArray(i) = []
  1 Comment
Stephen23 on 25 Sep 2022
While MATLAB allows you to iterate over any array type, in practice (as soon as you do anything more complex than just looking at each single element) it is almost always simpler and clearer to iterate over indices into that array.

Sign in to comment.

Accepted Answer

dpb on 25 Sep 2022
Edited: dpb on 26 Sep 2022
"The MATLAB way" would be to write
or the construct to save only the ones that aren't empty...
The obvious way to write the above looping construct is that it isn't a fitting place to use the range-based construct -- "if it doesn't fit..."
Avoid the ugly constructs by using something like
for i = 1:numel(myObjectArray):-1:1
if ...
myObjectArray(i) = [];
NB: As @Stephen23 points out, when deleting elements from an array, since numbering of those elements is sequential and begins with numero uno and goes up, to ensure correctness in the operation, one must operate from the top down. That's yet another reason the range-based loop structure isn't appropriate in this application.
dpb on 25 Sep 2022
@Stephen23 -- that's good point I forgot to incorporate being only focussed on the fact that the loop isn't the right way here, anyway, probably.
I'll update the Answer to incorporate...
SoderlingPotro on 1 Oct 2022
Thank you, it was indeed the fact that I was trying to do deletion with i as an iterator which made me ask this question (when deleting an object, i would then try to access an element which did not exist). But I noticed the range based for loop method (myObjectArray(i) = []) does dynamically update when an element is removed, so it won't look for an object which does not exist. Either way, iterating backwards with i seems like the best way.

Sign in to comment.

More Answers (2)

Walter Roberson
Walter Roberson on 25 Sep 2022
When you "for" name=array then matlab iterates over the columns of the array, setting the variable to each column in turn. So tmpObject is already the result of indexing your object array. And then you are trying to use that result to index your object array.
Imagine for example that the object array was a row vector of three figure handles, figure 1, 2, and then 1 again. The for loop would assign one of the figure handles to the variable, and then you would try to index the vector of figure handles by a figure handle. And you would want to do so in a way that even though the first and third entry refer to the same figure and so the same content would be assigned, you would want want different locations to be referred to when used as an index.
Would it be possible to define an object class in such a way that the result of the implicit indexing for for loop purposes was something that you could use the properties of, but could also use the value as an index into the array? I would not rule out the possibility if you define subsref carefully. In particular if you define subsref to return an object that has some kind of unique key for each element, and you define subsasgn to be able to use such objects to match the key to location... ummm I just realized that I am unclear on how deletion works internally. The work flow you are using just might be possible with sufficient coding.
... but using integer indices is a lot simpler.

Shadow on 3 Apr 2024
Not for deleting stuff inside the array but it provides an index:
enumer = @(my_array) cell2mat(arrayfun(@(x,idx) struct("cargo",x,"idx",idx), my_array(:).', 1:numel(my_array(:).'),UniformOutput=false));
data = string(('A':'F').')
data = 6x1 string array
"A" "B" "C" "D" "E" "F"
for elem = enumer(data)
disp("Element " + string(elem.cargo) + " with index " + string(elem.idx))
Element A with index 1 Element B with index 2 Element C with index 3 Element D with index 4 Element E with index 5 Element F with index 6




Community Treasure Hunt

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

Start Hunting!