How to remove cell array satisfying specific conditions
3 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
JH
el 25 de Sept. de 2015
Comentada: JH
el 28 de Sept. de 2015
Hi all,
I have a cell array with n vectors of different lengths m. I want to remove the cells, whose vectors satisfy a specific condition for which all the elements of the individual vectors need to be scanned. Something like that:
for c = 1 : length(cutForce)
for d = round(length(cutTime{c})/4) : round(3*length(cutTime{c})/4)% searching for data between the 1st and 3rd fourth of the vector
if min(cutForce{c}(d)) < 300
cutForce(c) = [];
end
end
end
Unfortunately the code doesn't work. I am new to programming. Help me please.
0 comentarios
Respuesta aceptada
Guillaume
el 25 de Sept. de 2015
Editada: Guillaume
el 26 de Sept. de 2015
There are two issues with your code:
- You're performing the min on just one element, since d is scalar. You either meant to just compare the element value to 300 (without min):
for d = ...
if cutForce{c}(d) < 300
...
or you meant to use min, in which case you did not need a loop:
d = round(...) : round(...) %d is just a list of indices
if min(cutForce{c})d) < 300
...
- More importantly, you are removing element of a sequence while you're iterating over an index of the sequence which does not know that elements have been remove. For example, imagine that when c = 2 your condition is true. You delete the second element, so third element becomes 2nd, 4th becomes third, etc. On the next pass of the loop, c becomes 3, which was the 4th element before. So you never test the original 3rd. Furthermore, when you reach the end, there's less elements than expected, so you're going to get an indexing error. The solution to this is to gather the list of indices to remove in the loop and perform the deletion afterward:
todelete = false(size(cutForce)); %vector that keeps track of which elements to delete
for c = 1:numel(cutForce) %I prefer numel to length as it works with n-d arrays.
testvector = cutForce{c}(round(numel(cutTime{c})/4) : round(3*numel(cutTime{c})/4));
%the above can also be written using the end keyword:
%testvector = cutForce{c}(round(end/4) : round(3*end/4));
todelete(c) = min(testvector) < 300; %either true or false
end
cutForce(todelete) = []; %delete all elements at once after the loop
todelete = cellfun(@(v) min(v(round(end/4):round(3*end/4))) < 300, cutForce);
cutForce(todelete) = [];
3 comentarios
Guillaume
el 26 de Sept. de 2015
There was a stupid mistake in both of my codes that I've now fixed.
With the example matrices that you've posted 3 elements of cutForce are removed.
Más respuestas (1)
the cyclist
el 25 de Sept. de 2015
Editada: the cyclist
el 25 de Sept. de 2015
I have not looked at the details of your algorithm. One likely problem is that as you remove elements of the cell array inside your for loop, the index c begins to point to the wrong element. For example, if you happen to remove the first element, then the next time through the loop, c = 2 refers to the 2nd element of the shortened cell array, which is actually the 3rd element of the original vector.
There are a couple solutions. The easier one to understand for a beginner is to, in your for loop, only identify and store the elements you want to remove (say, in variable indicesToRemove), but don't remove them yet. Then, as a second step, do something like
cutForce(indicesToRemove) = [];
The more sophisticated way to do this is to use the cellfun command, which would allow you to test the condition on all cell array elements at once.
Ver también
Categorías
Más información sobre Loops and Conditional Statements en Help Center y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!