1

我有 n 个不同长度的单元向量,称之为c{i}, i=1,2,...,n

我想知道是否有c{j}的子集c{i},例如:

c{1}=[1 2 3 4 5 6]; c{2}=[1 3 5 7];c{3}=[2 4 6 8];
c{4}=[1 4 6];c{5}=[3 7];

那么我希望我能找到那c{4}是 的子集c{1}c{5}是 的子集c{2}

我用了两个for循环和intersect函数可以处理,但我希望我最多可以用一个循环来处理它,有什么办法可以实现吗?

4

3 回答 3

1

这是一个使用的选项nchoosek-cellfun当然它也是一个变相的循环:

c{1} = [1 2 3 4 5 6];
c{2} = [1 3 5 7];
c{3} = [2 4 6 8];
c{4} = [1 4 6];
c{5} = [3 7];
combs = nchoosek(1:numel(c),2);
subC = cell(size(combs,1),1);
for i = 1:size(combs,1)
    subC{i} = intersect(c{combs(i,:)});
end

这导致单元格数组

subC = 

    [1x3 double]
    [1x3 double]
    [1x3 double]
    [         3]
    [1x0 double]
    [         1]
    [1x2 double]
    [1x2 double]
    [1x0 double]
    [1x0 double]

每个单元格subC对应于单元格索引的交集combs(如果首选,可以在循环内轻松构建矩阵形式)。

编辑:如果您只是想知道一个向量是否是另一个向量的子集,那么您可以使用subCand combsfrom above 来确定或直接计算它

combs = nchoosek(1:numel(c),2);
isSubC = logical(eye(numel(c)));
for i = 1:size(combs,1)
    subC = intersect(c{combs(i,:)});
    isSubC(combs(i,1),combs(i,2)) = isequal(subC,c{combs(i,2)});
    isSubC(combs(i,2),combs(i,1)) = isequal(subC,c{combs(i,1)});
end

whereisSubC(i,j)指定是否 c{j}是 的子集c{i}

于 2013-08-17T19:47:39.523 回答
1

在其他答案的基础上,您还可以使用ismember

sets = {[1 2 3 4 5 6], [1 3 5 7], [2 4 6 8], [1 4 6], [3 7]};

N = numel(sets);          % number of sets
idx = nchoosek(1:N,2);    % indices of combinations
subsets = false(N,N);
for i = 1:size(idx,1)
    a = idx(i,1); b = idx(i,2);

    % check that set A is a subset of B, and the other way around as well
    subsets(a,b) = all(ismember(sets{a},sets{b}));
    subsets(b,a) = all(ismember(sets{b},sets{a}));
end

我们得到一个逻辑矩阵:

>> subsets
subsets =
     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0
     1     0     0     0     0
     0     1     0     0     0

其中非零表示子集关系:

>> [i,j] = find(subsets)
i =
     4
     5
j =
     1
     2

iec{4}是 的子集c{1},并且c{5}是 的子集c{2}

注意:显然任何集合都是它自己的一个子集,所以subsets矩阵的对角线也应该是1。如果你想使用,你可以添加:

subsets(1:N+1:end) = true;
于 2013-08-18T01:07:40.643 回答
0

您可以使用 cellfun,但正如此处所述,这不是一个好主意。

为此,只需一个循环:

c{1}=[1 2 3 4 5 6]; c{2}=[1 3 5 7];c{3}=[2 4 6 8];
c{4}=[1 4 6];c{5}=[3 7];
cSize = numel( c);
isect=cell(1,cSize)
for k=1:cSize
  isect{k}=cellfun(@(in) intersect(in,c{k}),c,'UniformOutput',false);
end

可以重复此过程以消除另一个:

c{1}=[1 2 3 4 5 6]; c{2}=[1 3 5 7];c{3}=[2 4 6 8];
c{4}=[1 4 6];c{5}=[3 7];
isect=cellfun(@(in) cellfun(@(in2) intersect(in,in2),c,'UniformOutput',false),c,'UniformOutput',false);

isect{i}{j}c{i}是从到的交点{j}

注意: cellfun 将在单元格值上进行内部循环,因此实际上,您并没有删除循环。


虽然这不是最初的问题,但找到子集:

c{1}=[1 2 3 4 5 6]; c{2}=[1 3 5 7];c{3}=[2 4 6 8];
c{4}=[1 4 6];c{5}=[3 7];c{6}=[];
isSubset=cell2mat(cellfun(@(in) cellfun(@(in2) isequal(intersect(in,in2),in)|isempty(in),c),c,'UniformOutput',false)');

结果:

是子集 =

 1     0     0     0     0     0
 0     1     0     0     0     0
 0     0     1     0     0     0
 1     0     0     1     0     0
 0     1     0     0     1     0
 1     1     1     1     1     1

k如果是mby doing的子集,则返回一个布尔值isSubset(k,m)

于 2013-08-17T19:20:44.440 回答