Choosing cells in a structure with fields that contain random elements

63 views Asked by At

I really appreciate it if anyone could answer this question. I asked many people and yet could not find a good answer.

DATA = struct ('Direction',{[1,1,1,1],[1,1,2,1],[2,2,2,2,2],[2,2,2,2,1,2],[2,2,2,2],[1,4,3,5,2]); 

I have this structure and I am using the following code to the ones with a specific direction:

DATA = DATA(arrayfun(@(x) sum(x.Direction == 2) + 1 >= numel( x.Direction ), DATA))
DATA = DATA(arrayfun(@(x) sum(x.Direction == 1) + 1 >= numel( x.Direction ), DATA))

this will allow me to choose for example only cells with 2 as their direction and allow for one different number like in [2,2,2,2,1,2].

I was just wondering if there is a way to choose the cells with random direction? ie. [1,4,3,5,2] (elements are random and may or may not contain 1 or/and 2)

ps:

I do not know how to write it but I want to have a code that can compare the matrix element, element by element (like what I have above) and the moment in reaches an element that is not 1 or 2, it selects it as random! meaning that the random matrix can have 1 and/or 2 but the code should skip that until it reaches a non 1 or 2 element.

just to clarify:

I have 3 conditions

((1)) either all the elements of the field are 1 with maximum one element that is not 1 and is 2.

((2)) or all the elements of the field are 2 with maximum one element that is not 2 and is 1.

((3)) and finally the elements are random, but they can still have many 1's and 2's and that is just by chance.

by selecting as "random" I mean selecting the third category. my code works for the first two categories but for the third one it removes some matrices that are actually random but have more than one element that is 1 and/or 2 since the code allows for only one different element

Thank you.

1

There are 1 answers

1
beaker On BEST ANSWER

Given that category 3 is simply anything not in categories 1 or 2, we can figure out what elements belong in category 3 in a couple of ways. We can get the indices of categories 1 and 2 and remove them from the set of all indices, or we can invert the logic used to select categories 1 and 2.

Method 1

%// Category 2
cat2Indices = find(arrayfun(@(x) sum(x.Direction == 2) + 1 >= numel( x.Direction ), DATA));
DATA2 = DATA(cat2Indices);
%// Category 1
cat1Indices = find(arrayfun(@(x) sum(x.Direction == 1) + 1 >= numel( x.Direction ), DATA));
DATA1 = DATA(cat1Indices);
%// Category 3
cat3Indices = [1:length(DATA)];
cat3Indices = setdiff(cat3Indices, cat1Indices);
cat3Indices = setdiff(cat3Indices, cat2Indices);
DATA3 = DATA(cat3Indices);

This just saves the indices from the first two categories and calculates the set difference between those indices and the list of all indices in DATA.

Method 2

%// Category 2
DATA2 = DATA(arrayfun(@(x) sum(x.Direction == 2) + 1 >= numel( x.Direction ), DATA))
%// Category 1
DATA1 = DATA(arrayfun(@(x) sum(x.Direction == 1) + 1 >= numel( x.Direction ), DATA))
%// Category 3
DATA3 = DATA((arrayfun(@(x) sum(x.Direction == 1) + 1 < numel(x.Direction), DATA)) & ...
            (arrayfun(@(x) sum(x.Direction == 2) + 1 < numel(x.Direction), DATA)))

I've changed each of the inequalities from >= to < and performed a logical AND to make sure both inequalities hold.


Also note that your functions don't do precisely what your text descriptions say. For category 1 you say:

((1)) either all the elements of the field are 1 with maximum one element that is not 1 and is 2.

But your code will accept [1 1 1 1 5]. If it is important to exclude this possibility you need to change your logic.