Trouver des indices d'éléments dans un tableau basé sur une recherche à partir d'un autre tableau

Imaginons que j'ai deux tableaux:

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

b = [5, 9, 6];

Je veux trouver les indices des valeurs de b dans a (seulement le premier coup) ie:

c = [3, 6, 5];

Existe-t-il un moyen natif Matlab facile de le faire sans boucler et rechercher.

J'ai essayé d'utiliser find() avec:

find(a == b)

Et cela fonctionnerait si vous faisiez ceci:

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

Mais il serait idéal que ce soit plus facile que cela.

25
demandé sur Fantastic Mr Fox 2012-07-20 06:28:12

8 réponses

C'est en fait intégré dans ismember. Vous avez juste besoin de définir le bon drapeau, alors c'est un one liner et vous n'avez pas besoin d'arrayfun. Les Versions plus récentes que R2012b utilisent ce comportement par défaut.

À L'origine, ismember retournerait la dernière occurrence s'il y en a plusieurs, le drapeau R2012a le fait retourner le premier.

Voici mes résultats de test:

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
16
répondu scenia 2014-01-24 15:43:58

Vous pouvez compacter votre boucle for facilement avec arrayfun dans un simple one-liner:

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

Voir aussi la réponse de Scenia pour les nouvelles versions de matlab (>R2012b).

20
répondu Gunther Struyf 2017-05-23 12:32:25

C'est un correctif à l' ismember approche @Poursuite suggéré. De cette façon, il gère plusieurs occurrences de l'un des nombres, et renvoie le résultat dans le bon ordre:

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

Le résultat:

>> c
c =
     3     6     5
5
répondu Amro 2017-05-23 12:17:34
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

Note: j'ai ajouté un supplément de 6 à la fin de a pour démontrer la recherche uniquement la première occurrence de chaque valeur.

4
répondu tmpearce 2012-07-20 03:12:32

Vous pouvez essayer ceci:

[c,ind_a] = intersect(a,b)
4
répondu twerdster 2013-09-09 18:52:08

Avez-vous essayé ismember?

c_logical_mask = ismember(a, b);

Ou

c_indexes = find(ismember(a, b));
1
répondu Pursuit 2012-07-20 03:38:44
a = [1, 2, 5, 7, 6, 9, 8, 3, 4, 7, 0];
b = [5, 9, 6];
c = dsearchn(a',b');

Matlab nécessite a et b doivent être des vecteurs de colonne, d'où la transposition.

1
répondu glarson 2013-08-01 15:24:04

Similaire à la réponse de @tmpearce , mais peut-être plus rapide:

[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
répondu Luis Mendo 2017-05-23 12:10:19