Reputation: 197
This is a follow up question of How to delete element from cell arrays after comparisons without causing cell arrays to get empty? for which i got a partial solution. following is the code:
A = cell(2);
A{1} = [2 4];
A{3} = [3 2 0];
A{4} = 1;
celldisp(A) % A contains one 2, an empty cell, a double array and a 1.
AWithout2ButNotEmptied = cellfun(@(x) x( (x~=2) | (numel(x)<2) ), A,'UniformOutput', false);
celldisp(AWithout2ButNotEmptied)
output of above code is:
A{1,1} =
2 4
A{2,1} =
[]
A{1,2} =
3 2 0
A{2,2} =
1
AWithout2ButNotEmptied{1,1} =
4
AWithout2ButNotEmptied{2,1} =
[]
AWithout2ButNotEmptied{1,2} =
3 0
AWithout2ButNotEmptied{2,2} =
1
output shows that A{1,1}
is equal to 4
and is not emptied after deletion of 2
, because its length is less than two (its length is one). A{1,2}
has the element equal to 2 removed. A{2,1}
is already empty and is left unchanged. A{2,2}
has length 1, but is not equal to 2, so it is left unchanged as well so, the check is performed only on number 2
whether to be deleted or not.
How can i change this code to remove any number x(not only 2)
from any cell element if it does not causes any other array to become empty.
I want to do this for any value of x(1,...,n)
in my cell i don't want to remove any specific numbers it could be any number x
from the cell arrays.
for example:
OccursTogether{1,1} =
4 11 14
OccursTogether{1,2} =
1
OccursTogether{1,3} =
[]
OccursTogether{1,4} =
1 4 8 14 15 19 20 22
OccursTogether{1,5} =
4 11
the result i want is as follows;
OccursTogether{1,1} =
11
OccursTogether{1,2} =
1
OccursTogether{1,3} =
[]
OccursTogether{1,4} =
1 8 15 19 20 22
OccursTogether{1,5} =
11
as u can see 4
and 14
is removed from multiple cells which gave the above result. we cannot remove 11
because it will cause empty location at {1,1}
and {1,5}
same checks should be applied on every number x
before removing it.
Upvotes: 3
Views: 75
Reputation: 4573
My answer to your previous question is updated now.
I copied it here:
Use the following, where C
stands for your OccursTogether
cell (shorter, thus easier to read for this answer). The comments in the code explain a bit what the corresponding lines do.
C = cell(3,2);
C{1,1} = [4 11 14];
C{2,1} = 1;
C{2,2} = [1 4 8 14 15 19 20 22];
C{3,2} = [4 11];
celldisp(C)
C = cellfun(@unique, C, 'UniformOutput', false); % remove duplicates from elements of C
numsInCell = unique([C{:}]); % numbers in cell, sorted
for n = numsInCell % loop over numbers in cell
lSetIs1 = cellfun(@numel,C) == 1; % length of set is 1
nInSet = cellfun(@(set) any(set==n), C); % set contains n
nIsUnique = sum(nInSet(:))==1; % n occurs once
condition = ~nIsUnique & ~any(nInSet(:) & lSetIs1(:)); % set neither contains n and has length of 1, nor n is unique
if condition % if false for all sets...
C = cellfun(@(set) set(set~=n), C, 'UniformOutput', false); % ... then remove n from all sets
end
end
celldisp(C)
Notice I use logical indexing in the line in the for
-loop starting with C = cellfun(...
, which saves you an additional for
-loop over the elements of C
. The MATLAB function cellfun
performs the function handle in its first argument on the elements of the cell in the second argument. This is a very useful tool that prevents the use of many for
-loops and even some if
-statements.
Upvotes: 1