【问题标题】:Check if cell array is a subset of a nother in Matlab检查单元格数组是否是 Matlab 中另一个的子集
【发布时间】:2013-04-13 07:31:51
【问题描述】:

我有两个字符串元胞数组,如下所示

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

我想检查 A 是否是 B 的子集,这意味着 A 中的每个单元格在 B 中都有一个超级单元格。在给定的示例中不是因为 A 包含 {d,e} 而 B 没有任何具有这些或更多元素的单元格。 我认为 ismember 在这种情况下应该很有用,但我就是无法写下逻辑。

谢谢!

【问题讨论】:

    标签: arrays matlab cell subset


    【解决方案1】:

    给定 A 和 B

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

    我们可以定义一个函数isSubset,如下:

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

    并对其进行测试:

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

    现在我们可以使用isSubSetcellfun 来定义一个函数isSubSetOfAny,它检查一个特定的子集是否是一组集合的子集,如下所示:

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

    并对其进行测试:

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

    现在我们可以使用isSubSetOfAny 加上cellfun(再次)定义isEachMemberASubsetOfAny,它执行您描述的操作:

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

    并对其进行测试:

    isEachMemberASubsetOfAny(B, A)    %Returns false
    
    A_1 = {{'a','b'},{'c'},{'e'}};    %Define a variant of `A`
    isEachMemberASubsetOfAny(B, A_1)  %Returns false
    

    【讨论】:

      【解决方案2】:

      a、b等有哪些类型?如果它们是字符串,您可以使用setdiff 来测试一个集合是否包含在另一个集合中。适当使用cellfunanyall 应该可以做到。像这样:

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

      如果它们是其他类型,您可以制作一个简单的 m 文件来检查超级单元。将isempty(setdiff(a,b)) 替换为对此函数的调用。它必须遍历a 的元素并检查每个元素是否存在于b 中。

      【讨论】:

      • 谢谢您的代码似乎可以正常工作,但我无法理解。您能简单地展开它吗?
      • isempty(setdiff(a,b)) 检查b 是否是a 的超集。两个cellfuns遍历AB的元素。如果A 的所有元素都可以找到至少一个B 的超集元素,则最终结果为真。
      【解决方案3】:

      假设 a、b 等是字符串,您可以执行以下操作:

      对于 A 的每个单元格,遍历 B 并查看 B 中是否存在一个单元格,该单元格中的所有元素都是其成员。这是一个例子:

       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
      

      【讨论】:

        【解决方案4】:

        怎么样:

        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
        

        [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
        

        【讨论】:

        • 尽快打破循环应该会比基于 cellfun 的方法(包括我自己的方法)带来相当大的性能提升。
        猜你喜欢
        • 2023-03-18
        • 2010-09-24
        • 2012-05-20
        • 1970-01-01
        • 1970-01-01
        • 2016-12-13
        • 2021-07-10
        • 2021-09-26
        相关资源
        最近更新 更多