在Matlab中找到两个数组结构的交集

时间:2013-05-29 05:27:07

标签: algorithm matlab

如何在Matlab中找到以下两个数组结构的交集。

例如,我有两个结构数组ab

a(1)=struct('x',1,'y',1);
a(2)=struct('x',3,'y',2);
a(3)=struct('x',4,'y',3);
a(4)=struct('x',5,'y',4);
a(5)=struct('x',1,'y',5);


b(1)=struct('x',1,'y',1);
b(2)=struct('x',3,'y',5);

我希望找到ab的交集如下:

c = intersect(a,b)

c应该

c = struct('x',1,'y',1);

但是当我输入intersect(a,b)时似乎错了,因为ab的元素都是结构。我怎样才能解决这个难题。感谢。

3 个答案:

答案 0 :(得分:4)

优雅的解决方案是为intersect提供一个比较运算符(例如,C++)。 不幸的是,Matlab似乎并不支持这种功能/灵活性。

您的问题的解决方法是

% convert structs into matrices
A = [[a(:).x];[a(:).y]]';
B = [[b(:).x];[b(:).y]]';
% intersect the equivalent representation
[C, ia, ib] = intersect( A, B, 'rows' );
% map back to original structs
c = a(ia);

或者,您是否考虑使用从句柄类派生的类对象替换结构?有可能重载类的relational operators,然后应该可以直接对类对象进行排序(我没有仔细研究过这个解决方案 - 这只是我头脑中的一个提议)。

答案 1 :(得分:4)

Shai方法的一般变体是:

A = cell2mat(permute(struct2cell(a), [3 1 2]));
B = cell2mat(permute(struct2cell(b), [3 1 2]));
[C, ia] = intersect(A, B, 'rows');
c = a(ia);

这样您就不需要显式指定所有结构域。当然,如果struct字段包含非数字值,这将不起作用。

任何类型和尺寸的字段的通用方法

如果您不确定结构中存储的数据的类型和大小,interesect将不会删除它。相反,您必须使用isequal循环。我在这里使用arrayfun来获得优雅:

[X, Y] = meshgrid(1:numel(a), 1:numel(b));
c = a(any(arrayfun(@(m, n)isequal(a(m), b(n)), X, Y)));

答案 2 :(得分:1)

系统方法是产生hash - 然后使用intersect:

hash_fun = @(x) sprintf('x:%g;y:%g',x.x,x.y);

ha = arrayfun(hash_fun,a,'UniformOutput',false);
hb = arrayfun(hash_fun,b,'UniformOutput',false);

[hi,ind_a,ind_b]=intersect(ha,hb)
res=a(ind_a) % result of intersection