How to remove cell array satisfying specific conditions
3 次查看(过去 30 天)
显示 更早的评论
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 个评论
采纳的回答
Guillaume
2015-9-25
编辑:Guillaume
2015-9-26
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 个评论
Guillaume
2015-9-26
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.
更多回答(1 个)
the cyclist
2015-9-25
编辑:the cyclist
2015-9-25
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.
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Loops and Conditional Statements 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!