web-dev-qa-db-fra.com

Trouver des index d'éléments dans un tableau en se basant sur une recherche dans un autre tableau

Imaginez 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), c'est-à-dire:

c = [3, 6, 5];

Existe-t-il un moyen simple, natif Matlab, de le faire sans faire de boucles ni chercher.

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 ce serait idéal pour que ce soit plus facile alors. 

26
Fantastic Mr Fox

Ceci est en fait construit dans ismember . Vous avez juste besoin de définir le bon drapeau, alors il s’agit d’un one-liner et vous n’avez pas besoin de arrayfun. Les versions plus récentes que R2012b utilisent ce comportement par défaut.

À l'origine, ismember renverrait la dernière occurrence s'il y en a plusieurs, le drapeau R2012a oblige celle-ci à renvoyer la première.

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
17
scenia

Vous pouvez facilement compresser votre boucle for avec arrayfun en une ligne simple:

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

voir aussi Réponse de Scenia pour les nouvelles versions de matlab (> R2012b).

20
Gunther Struyf

Ceci est un correctif à l'approche ismember que @Pursuit a 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
Amro

Vous pouvez essayer ceci:

[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

Remarque: j'ai ajouté un 6 supplémentaire à la fin de a pour montrer que seule la première occurrence de chaque valeur était trouvée.

4
tmpearce

Avez-vous essayé ismember?

c_logical_mask = ismember(a, b);

ou

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

Similaire à @ tmpearce's answer , mais peut-être plus rapidement:

[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 nécessite a et b doivent être des vecteurs colonne, d’où la transposition.

1
glarson