在Matlab中有效地计算单元阵列元素之间的成对交叉

时间:2015-11-09 15:30:49

标签: matlab vectorization cell-array

假设您有2个单元格数组:

tri1(4x1细胞)

[1; 3; 4]
[2; 4]
[1; 2; 3]
[1; 3; 4]

和tri2(4x1细胞)

[1; 2; 3]
[1; 2; 3]
[1; 3; 4]
[2; 4]

并且您想要计算每2个相应单元格元素之间的交集。在这个例子中,结果将是这样的:

tri12(4x1细胞)

[1; 3]
2
[1; 3]
4

当前我使用 cellfun 计算此交集如下:

tri12 = cellfun(@(t1, t2){intersect(t1, t2)}, tri1, tri2);

但是,当单元格数组很大时,这非常慢。

我的问题,是否有更快的方法来计算相同的交叉点结果而无需使用 cellfun

请注意,无需维护所涉及对象的确切当前格式(即单元格数组)。因此,任何可以计算相同结果的快速解决方案都是完美的。

4 个答案:

答案 0 :(得分:2)

在Matthew Gunn解决方案的基础上,我发现优雅,在有界非负整数的情况下,上限相对较大,当细胞非常大时。

我们基本上可以将它应用于每对单元格元素,同时预先分配可以为每对重用的长行逻辑,同时注意每次清理它。这看起来像是:

function C1_C2 = fast_intersect( C1, C2, max_int )

    x = false(1,max_int);
    y = false(1,max_int);

    C1_C2 = cellfun( @fast_intersect_impl, C1, C2, 'UniformOutput', false );


    function ab = fast_intersect_impl(a,b)

        x(a)=true; y(b)=true;
        ab = find(x & y);
        x(a)=false; y(b)=false;

    end

end

答案 1 :(得分:1)

如果集合中的数字是从1到不是那么大的元素索引的整数,则可以使用列作为指标来表示矩阵中的集合。 (即X(i,j)是关于元素j是否在集合i中的二进制指示符。)用矩阵加载矩阵:

X = false(length(tri1), MAXELEMENT);
for i=1:length(tri1), 
  X(i,tri1{i}') = true; 
end
Y = false(length(tri2), MAXELEMENT);
for i=1:length(tri2), 
  Y(i,tri2{i}') = true; 
end

然后交叉点只是myintersection = X & Y;,应该超级快。

答案 2 :(得分:0)

我认为您的解决方案没有任何改进。但是,你确定你写的并不意味着

tri12 = cellfun( @(t1, t2) intersect(t1, t2), tri1, tri2, 'UniformOutput', false );

代替?也就是说,为每对夫妇返回一个数组,而不是一个单元格数组?这可以加速一点。

intersect在数字数组中使用unique,这与没有进一步约束的情况一样好。但是,如果您知道数组中的值都是以相对较小的值(例如数千万以下)为界的正整数,那么您可以在{{1}中制作 ad hoc 解决方案。使用bin计数。 Matlab等价物将使用C/Mex,但我怀疑它会比accumarray更快。

答案 3 :(得分:0)

我写了a script做成对相交。

您需要先将单元格转换为矩形表,然后再执行MetaIntersect(A,B)