How to remove rows from a struct based on a condition? - arrays

I want to delete rows from a struct using a condition which is if hsvmean field = 0 then delete the row. I tried this code:
for j =1:length(selectedIms) % the length of selectedIms is 100
if selectedIms(j).hsvmean == 0
selectedIms(j)=[];
end
end
But I get this error:
Index exceeds the number of array elements (73).
Error in HSVColorSelection (line 57)
if selectedIms(j).hsvmean == 0
How can I delete these items?

Here’s a solution in case someone needs it. Create a new struct in which there would only be the filtered rows
newSelectedlms = meanValues([meanValues.selected_ims]~= 0);

You’re deleting elements, making the array smaller, as you loop over the elements. The end index you loop over is determined at the start of the loop, hence you will index past the end of the array. You are also skipping over elements.
One simple solution is to loop starting at the back:
for j=length(selectedIms):-1:1
...
end
The other solution is to delete all elements at once. You could build a list of indices to delete in the loop, then delete those elements after the loop. Or do it without a loop:
selectedIms([selectedIms.hsvmean] == 0) = [];

Related

MATLAB: deleting elements from multi-level cell

I've got a large multi-level cell and I'm trying to delete parts of it within a for loop but can't get past "Error: The expression to the left of the equals sign is not a valid target for an assignment."
Have tried a few versions and keep hitting the same error.
for i=1:length(List{1}{17}{imagenum})
if List{1}{17}{imagenum}(i)>1
List{1}{17}{imagenum}(i)=[];
end
end
Separate question: When I delete parts of a cell/anything within a for loop, is there a standard/smart way of making sure the for loop stays on track? I've been using a variable to keep track of deletions but I'm assuming there's a smarter way of doing this:
deletions=0;
for i=1:length(List{1}{17}{imagenum})
if List{1}{17}{imagenum}(i-deletions)>1
List{1}{17}{imagenum}(i-deletions)=[];
deletions=deletions+1;
end
end
Let's assign List{1}{17}{imagenum} to a:
a = List{1}{17}{imagenum};
Is 'a' cell or array? If it is array:
for i = numel(a):-1:1
if a(i)>1, a(i) = []; end
end
Easier way should be:
a(a>1) = [];
If it is cell:
for i = numel(a):-1:1
if a{i}>1, a(i) = []; end
end
General rule: when you delete items in a loop, you start from the end, not the beginning.

VBA nested for loop won't Run

Hi I'm working on a macro in VBA for excel. I have a nested for loop in my code as seen below. The second loop does not run; even a MsgBox() command within the second loop doesn't result in any action and the program just seems to skip over the nested loop with no reported errors.
In plain English this nested loop should:
1) Take the string from the i entry in the array categories_string (first for loop).
2) iterate through the 300+ rows in column "AE" in the excel file (second for loop, "length" is the length of the column of data in "AE")
3) look for string matches and add 1 to the corresponding entry in the categories_value array which is populated with variables set to 0 (the if statement).
For i = LBound(categories_string) To UBound(categories_string)
For p = 1 To p = length
If Worksheets("sheet1").Cells(p + 2, "AE").Value = categories_string(i) Then
categories_value(i) = categories_value(i) + 1
End If
Next
Next
Change
For p = 1 To p = length
to
For p = 1 To length
Should fix you right up.
You may want to consider Scott Cranner's comment as well, especially if your categories_string is large and length is large. Or, just do it for the practice

Pulling out specific column when sometimes, the array is empty

I am trying to pull out a column from inside a cell. However, sometimes, the cell is empty.
For example, if in this line, I try to pull out the last column inside PM25_win{i}, it sometimes has an array inside of size nx28. However, sometimes, the array is zero.
for i = 1:length(years)-1
PM25 = table2array(PM25_win{i}(:,end));
end
When the array is empty, the code stops and I get the error
Subscript indices must either be real positive integers or logicals.
How can I account for both cases so that the code will simply create the PM25 variable as an empty array if PM25_win{i} is empty?
You could simply add an if-else statement in the for loop.
for i = 1:length(years)-1
if isempty(PM25_win{i}(:,end))
PM25 = [];
else
PM25 = table2array(PM25_win{i}(:,end));
end
end

Ignore empty cell array and execute the following cell

I want to make a condition that check if the cell array is empty then move to the next.
I got this index exceed matrix dimensions
Looking forward to hear from you
You can use isempty to check if an element is empty or not:
C = cell(5,1);
C{2} = 2;
for ind = 1:length(C)
if ~isempty(C{ind})
disp(['Processing C{' num2str(ind) '}']);
end
end
and never let index of C exceed length(C).

How to delete an element from an array, which is in looping ?

Following is a psuedo-code example of what I am trying to do. I loop over an array and delete elements based on a condition. Now the problem is when I remove the elements the size of myArray is changing, and I get an out of index exception. Any ideas on how to get around this?
for i = 1:size(myArray)
if myArray(i) == someValue
remove_from(myArray, i)
a simple solution for this problem is loop from the last to the first element.
for i = size(myArray):1
if myArray(i) == someValue
remove_from(myArray, i)

Resources