【问题标题】:Extending ismember to cells将 ismember 扩展到单元格
【发布时间】:2016-10-26 22:45:35
【问题描述】:

我已经搜索了论坛,但没有找到足够的信息来帮助我解决这个问题。

考虑集合(向量单元)

A = {[1],[1 2],[2],[1 2 3],[1 2 3 4],[1 3]}

我想构造一个矩阵B,看起来像

B = [1 1 0 1 1 1
     0 1 0 1 1 0
     0 1 1 1 1 0
     0 0 0 1 1 0
     0 0 0 0 1 0
     0 0 0 1 1 1]

矩阵 B 指定向量之间的成员关系。也就是说,第一行查看 A 中的第一个元素 [1],并检查它是否是其他向量的成员,如果是成员则放置 1,否则放置 0。

我可以使用两个 for 循环来做到这一点:一个在 A 的元素上,另一个嵌套在 A 的每个元素上,检查 A 的每个其他成员的成员关系。

我想避免使用 for 循环。有没有一个向量化的解决方案可以从 A 获得 B?

【问题讨论】:

    标签: matlab vectorization cells


    【解决方案1】:

    使用元胞数组很难避免循环,或者它们的表亲cellfun。我会这样做:

    [ii, jj] = ndgrid(1:numel(A)); % indices of all possible pairs
    result = cellfun(@(x,y) all(ismember(x,y)), A(ii), A(jj)); % see if all elements in the 
        % first are present in the second
    

    【讨论】:

    • 不错的解决方案。您提到 cellfun 是循环的表亲——它基本上只是遍历单元格的所有元素吗?
    • @jonem 是的,它从输入/s 中获取每个单元格并将指定的函数应用于它/它们。在性能方面,它类似于循环。单元格通常无法进行矢量化:-(
    【解决方案2】:

    嗯,你要求的,所以这是一个几乎*矢量化的解决方案,使用 bsxfunpermute -

    lens = cellfun('length',A) 
    vals = [A{:}]
    
    mask = bsxfun(@ge,lens,[1:max(vals)]')
    a = nan(size(mask))
    a(mask) = vals
    matches =  bsxfun(@eq,a,permute(a,[3,4,1,2]));
    out = bsxfun(@eq,squeeze(sum(any(matches,3),1)),lens(:))
    

    *:几乎是因为在cellfun('length',A)开头使用了cellfun,但由于它只是获取那里的单元格长度,所以计算上可以忽略不计。

    另外,请注意,这种方法会使用大量内存资源,因此可能没有好处,但只是尽可能尊重矢量化解决方案的要求!

    【讨论】:

      猜你喜欢
      • 2012-11-14
      • 1970-01-01
      • 2018-11-07
      • 1970-01-01
      • 2021-06-03
      • 1970-01-01
      • 1970-01-01
      • 2015-12-11
      • 2023-03-11
      相关资源
      最近更新 更多