Reputation: 83
I have a table like the above attachment. Column A and Column B contains some elements in terms of cell array. I want to create the third column (Level) as the resultant column; based on the following logic.
The row for which, value of cell A = value of cell B will be labeled1. (In the 3rd row, the value of column A=value of column B= 3, hence labeled 1).
Next, the preceding value will be removed from all the cells of column A; and the step 1 will be repeated until all the rows are labeled. (In the second step, 3 will be removed from all the cells, hence both row 1 and row 2 will be labeled as 2;In the final step, elements {1,2} will be further removed from the last row resulting the level as 3 )
I am using cell2mat and setdiff functions to compare the values across the cells, but I am not able to frame the above 2 logical steps to run my code successfully. I have just started learning MATLAB, Any help will be highly appreciated.
Upvotes: 4
Views: 210
Reputation: 125854
Here's the simplest answer I could come up with, using a single while loop and assuming the cells of A
and B
contain row vectors:
Level = zeros(size(A));
index = cellfun(@isequal, A, B);
while any(index)
Level(index) = max(Level)+1;
A = cellfun(@(c) {setdiff(c, unique([A{index}]))}, A);
index = cellfun(@isequal, A, B);
end
The above code first initializes a matrix of zeroes Level
the same size as A
to store the level values. Then it finds a logical index index
of where there are matching cell contents between A
and B
using cellfun
and isequal
. It will continue to loop as long as there are any matches indicated by index
. The corresponding indices in Level
are set to the current maximum value in Level
plus one. All the matching cell contents from A
are concatenated and the unique values found by unique([A{index}])
. A set difference operation is then used (along with cellfun
) to remove the matching values from each cell in A
, overwriting A
with the remaining values. A new index
for matches is then computed and the loop restarts.
Given the following sample data from your question:
A = {[1 2 3]; [2 3]; 3; [1 2 3 4]};
B = {[1 2]; 2; 3; 4};
The code returns the expected level vector:
Level =
2
2
1
3
Upvotes: 2
Reputation: 2462
Not my best work, i think it is possible to get rid of the inner loop.
% your testdata
A = {[1 2 3]
[2 3]
3
[1,2,4]};
B = {[1 2]
2
3
4};
Level = NaN(numel(B),1);
temp = A; % copy of A that we are going to remove elements from
k = 0; % loop couter
while any(isnan(Level)) % do until each element of Level is not NaN
k = k+1; % increment counter by 1
% step 1
idx = find(cellfun(@isequal,temp,B)); % determine which cells are equal
Level(idx) = k; % set level of equal cells
% step 2
for k = 1:numel(idx) % for each cell that is equal
%remove values in B from A for each equal cell
temp = cellfun(@setdiff,temp,repmat(B(idx(k)),numel(B),1),'UniformOutput',0);
end
end
Upvotes: 1