Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if cell array is a subset of a nother in Matlab

I have two cell arrays of strings as follows

 A={{a,b},{c},{d,e}}
 B={{a,b},{c,d},{e}}

I want to check if A is a subset of B, meaning that each cell in A has a super-cell in B. In the given example it is not since A contains {d,e} while B does not have any cell that has those or more elements. I think ismember should be useful in this case, but I just could not write down the logic.

Thank you!

like image 833
Evan Avatar asked Apr 19 '13 19:04

Evan


4 Answers

Given A and B

A={{'a','b'},{'c'},{'d','e'}}
B={{'a','b'},{'c','d'},{'e'}}

We can define a function isSubset, as follows:

isSubset = @(superSet,subSet)isempty(setdiff(subSet, superSet));

And test it:

isSubset(B{1}, A{1})  %true
isSubset(B{2}, A{2})  %true
isSubset(B{3}, A{3})  %false

Now we can use isSubSet and cellfun to define a function isSubSetOfAny, which checks to see if a particular subset is a subset of any of a set of sets, like this:

isSubSetOfAny = @(superSetSet, subSet) any(cellfun(@(x)isSubset(x, subSet), superSetSet));

And test it:

isSubSetOfAny(B, A{1})  %True
isSubSetOfAny(B, A{2})  %True
isSubSetOfAny(B, A{3})  %True

Now we can use isSubSetOfAny plus cellfun (again) to define isEachMemberASubsetOfAny, which performs the operation you describe:

    isEachMemberASubsetOfAny = @(superSetSet, subSetSet) all(cellfun(@(x)isSubSetOfAny(superSetSet, x), subSetSet));

And test it:

isEachMemberASubsetOfAny(B, A)    %Returns false

A_1 = {{'a','b'},{'c'},{'e'}};    %Define a variant of `A`
isEachMemberASubsetOfAny(B, A_1)  %Returns false
like image 173
Pursuit Avatar answered Sep 29 '22 10:09

Pursuit


How about something like:

function tf = is_subset(A,B)
    narginchk(2,2)
    assert(iscell(A) && all(cellfun(@iscellstr,A)));
    assert(iscell(B) && all(cellfun(@iscellstr,B)));

    for ia=1:numel(A)
        tf = false;
        for ib=1:numel(B)
            if all(ismember(A{ia},B{ib}));
                tf = true;
                break
            end
        end
        if ~tf
            break
        end
    end
end

With

[a,b,c,d,e] = deal('1','2','3','4','5');

A = {{a,b},{c},{d,e}};
B = {{a,b},{c,d},{e}};
is_subset(A,B)             %# false

B = {{a,b},{c,d,e},{e}};
is_subset(A,B)             %# true
like image 23
Amro Avatar answered Sep 29 '22 09:09

Amro


Assuming a,b etc are strings you could do the following:

For each cell of A loop through B and see whether there is a cell in B for which all elements in the cell are member. Here is an example:

 A={{'abc','b'},{'c'},{'d','e'}};
 B={{'aabc','b'},{'c','d'},{'d','e'}}; %Remove the first a to return true


 subset = true;
 for i = 1:length(A)
     found = false; 
     for j = 1:length(B)
         found = found || all(ismember(A{i},B{j}));
     end
     subset = subset && found;
 end
 subset
like image 21
Dennis Jaheruddin Avatar answered Sep 29 '22 09:09

Dennis Jaheruddin


What are the types of a, b, etc.? If they are strings, you can use setdiff to test whether one set is contained within another. Suitable use of cellfun and any or all should do it. Like so:

all(cellfun(@(a)any(cellfun(@(b)isempty(setdiff(a,b)),B)),A))

If they're some other type, you can make a simple m-file to check for a super-cell. Replace isempty(setdiff(a,b)) with a call to this function. It will have to loop through the elements of a and check for each one whether it exists in b.

like image 22
nhowe Avatar answered Sep 29 '22 09:09

nhowe