8

文字列のセル配列が2つあり、それらに同じ文字列が含まれているかどうかを確認したいと思います(同じ順序である必要はなく、同じ長さであるかどうかもわかりません)。

例えば:

a = {'2' '4' '1' '3'};
b = {'1' '2' '4' '3'};

また

a = {'2' '4' '1' '3' '5'};
b = {'1' '2' '4' '3'};

最初に考えstrcmpましたが、1つのセルの内容をループして、他のセルの内容と比較する必要があります。私はまたismember、次のようなものを使用して検討しました:

ismember(a,b) & ismember(b,a)

しかし、それらが同じ長さであることを事前に知りません(明らかに等しくない場合)。では、if / elseのケースをあまり多く記述せずに、この比較を最も効率的な方法でどのように実行しますか。

4

3 に答える 3

17

2つのセル配列の交点にない値を返す関数SETXORを使用できます。空の配列を返す場合、2つのセル配列には同じ値が含まれています。

arraysAreEqual = isempty(setxor(a,b));



編集:いくつかのパフォーマンス測定...

パフォーマンス測定に興味があったので、Amroによってリストされた2つのソリューション(ISMEMBERSTRCMP / CELLFUNを使用)に対してソリューションの速度をテストすると思いました。最初に2つの大きなセル配列を作成しました。

a = cellstr(num2str((1:10000).'));  %'# A cell array with 10,000 strings
b = cellstr(num2str((1:10001).'));  %'# A cell array with 10,001 strings

次に、各ソリューションを100回実行して、平均実行時間を取得しました。次に、交換abて再実行しました。結果は次のとおりです。

    Method     |      Time     |  a and b swapped
---------------+---------------+------------------
Using SETXOR   |   0.0549 sec  |    0.0578 sec
Using ISMEMBER |   0.0856 sec  |    0.0426 sec
Using STRCMP   |       too long to bother ;)

SETXORソリューションのタイミングが一貫して速いことに注意してください。にない要素がある場合、ISMEMBERソリューションは実際にはわずかに高速に実行されます。これは、計算の後半をスキップする短絡によるものです(すでにわかっていて、同じ値が含まれていないため)。ただし、のすべての値がにある場合、ISMEMBERソリューションは大幅に遅くなります。ab&&abab

于 2010-07-12T19:42:30.970 に答える
5

小さな変更を加えた場合と同じように、ISMEMBER関数を引き続き使用できます。

arraysAreEqual = all(ismember(a,b)) && all(ismember(b,a))

また、STRCMPを使用してループバージョンを1行で記述できます。

arraysAreEqual = all( cellfun(@(s)any(strcmp(s,b)), a) )

編集:私は別のSOの質問から適応した3番目のソリューションを追加しています:

g = grp2idx([a;b]);
v = all( unique(g(1:numel(a))) == unique(g(numel(a)+1:end)) );

同じ精神で、Imは(TIMEIT関数を使用して)時間比較を実行しました。

function perfTests()
    a = cellstr( num2str((1:10000)') );            %#' fix SO highlighting
    b = a( randperm(length(a)) );

    timeit( @() func1(a,b) )
    timeit( @() func2(a,b) )
    timeit( @() func3(a,b) )
    timeit( @() func4(a,b) )
end

function v = func1(a,b)
    v = isempty(setxor(a,b));                      %# @gnovice answer
end

function v = func2(a,b)
    v = all(ismember(a,b)) && all(ismember(b,a));
end

function v = func3(a,b)
    v = all( cellfun(@(s)any(strcmp(s,b)), a) );
end

function v = func4(a,b)
    g = grp2idx([a;b]);
    v = all( unique(g(1:numel(a))) == unique(g(numel(a)+1:end)) );
end

結果は同じ順序の関数になります(低いほど良い):

ans =
     0.032527
ans =
     0.055853
ans =
       8.6431
ans =
     0.022362
于 2010-07-12T20:06:09.977 に答える
2

関数を見てくださいintersect

MATLABヘルプの内容:

[c, ia, ib] = intersect(a, b)また、列のインデックスベクトルなどを返しますia。and ib (またはc = a(ia)andb(ib)c = a(ia,:)b(ib,:)).

于 2010-07-12T19:33:28.277 に答える