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}

交差関数で 2 つの for ループを使用して処理できますが、最大で 1 つのループを使用して処理できることを願っています。それを達成する方法はありますか?

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

結果は cell 配列になります

subC = 

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

内の各セルsubCは、内のセル インデックスの交点に対応しますcombs(必要に応じて、ループ内で行列形式を簡単に構築できます)。

編集:あるベクトルが別のベクトルのサブセットであるかどうかを単に知りたい場合は、上からsubCとを使用しcombsてこれを決定するか、直接計算することができます

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

whereは のサブセットであるisSubC(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 を使用することもできますが、ここで述べたように、それは良い考えではありません。

これを行うには、1 つのループを使用します。

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)');

結果:

isSubset =

 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がのサブセットである場合、ブール値を返しmますisSubset(k,m)

于 2013-08-17T19:20:44.440 に答える