web-dev-qa-db-ja.com

別の配列からの検索に基づいて配列内の要素のインデックスを見つける

私は2つの配列を持っていると想像してください:

a = [1, 2, 5, 7, 6, 9, 8, 3, 4, 7, 0];

b = [5, 9, 6];

私はa(最初のヒットのみ)のbの値のインデックスを見つけたい:

c = [3, 6, 5];

ループや検索をせずにこれを行う簡単なMatlabネイティブの方法はありますか。

私はfind()を以下で使用しようとしました:

find(a == b)

これを行うと動作します:

for i = 1:length(b)
    index = find(a == b(i));
    c = [c, index(1)]
end

しかし、これよりも簡単であることが理想です。

26

これは実際には ismember に組み込まれています。正しいフラグを設定するだけで、それは1つのライナーであり、arrayfunは必要ありません。 R2012bより新しいバージョンは、デフォルトでこの動作を使用します。

元々、 ismember は、複数ある場合は最後の出現を返しますが、R2012aフラグは最初の出現を返します。

テスト結果は次のとおりです。

a = [1, 2, 5, 7, 6, 9, 8, 3, 4, 7, 0, 6];
b = [5, 9, 6];

[~,c] = ismember(b,a,'R2012a');
>> c
c =
     3     6     5
18
scenia

Arrayfunを使用してforループを簡単に圧縮して、簡単な1行にまとめることができます。

arrayfun(@(x) find(a == x,1,'first'), b )

新しいMatlabバージョン(> R2012b)については Sceniaの答え も参照してください。

20
Gunther Struyf

これは、 @ Pursuit が提案したismemberアプローチの修正です。この方法では、1つの数字の複数の出現を処理し、正しい順序で結果を返します。

[tf,loc] = ismember(a,b);
tf = find(tf);
[~,idx] = unique(loc(tf), 'first');
c = tf(idx);

結果:

>> c
c =
     3     6     5
5
Amro

これを試すことができます:

[c,ind_a] = intersect(a,b)
4
twerdster
a = [1, 2, 5, 7, 6, 9, 8, 3, 4, 7, 0, 6];
b = [5, 9, 6];
[r c]=find(bsxfun(@eq,a,b')');
[~,ia,~]=unique(c,'first');
>> r(ia)

ans =

     3
     6
     5

注:追加の6aの最後に、各値の最初の出現のみを見つけることを示します。

4
tmpearce

ismemberを試しましたか?

c_logical_mask = ismember(a, b);

または

c_indexes = find(ismember(a, b));
1
Pursuit

@ tmpearce's answer に似ていますが、おそらくより高速です:

[valid, result] = max(bsxfun(@eq, a(:), b(:).')); %'// max finds first occurrence
result = result(valid); %// this is necessary in case some value of b is not in a
1
Luis Mendo
a = [1, 2, 5, 7, 6, 9, 8, 3, 4, 7, 0];
b = [5, 9, 6];
c = dsearchn(a',b');

Matlabでは、aとbが列ベクトルである必要があるため、転置が必要です。

1
glarson