假设您有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 ?
请注意,无需维护所涉及对象的确切当前格式(即单元格数组)。因此,任何可以计算相同结果的快速解决方案都是完美的。
答案 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)