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.
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
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).
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
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.
Avez-vous essayé ismember
?
c_logical_mask = ismember(a, b);
Ou
c_indexes = find(ismember(a, b));
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.
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