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

90 visualizaciones (últimos 30 días)
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) = []
end
end
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) = []
end
i=i+1;
end
Thanks
  1 comentario
Stephen23
Stephen23 el 25 de Sept. de 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.

Iniciar sesión para comentar.

Respuesta aceptada

dpb
dpb el 25 de Sept. de 2022
Editada: dpb el 26 de Sept. de 2022
"The MATLAB way" would be to write
isConditon=(EvaluateLogicalExpressionOverTheRange);
myObjectArray(isCondition)=[];
or the construct to save only the ones that aren't empty...
isConditon=(EvaluateLogicalExpressionOverTheRange);
myObjectArray=myObjectArray(~isCondition);
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) = [];
end
...
end
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.
  3 comentarios
dpb
dpb el 25 de Sept. de 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
SoderlingPotro el 1 de Oct. de 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.

Iniciar sesión para comentar.

Más respuestas (2)

Walter Roberson
Walter Roberson el 25 de Sept. de 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
Shadow el 3 de Abr. de 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))
end
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

Categorías

Más información sobre Matrix Indexing en Help Center y File Exchange.

Productos


Versión

R2022a

Community Treasure Hunt

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

Start Hunting!

Translated by