Funktion für 'Enthält die Matrix den Wert X?'

72

Gibt es eine eingebaute MATLAB-Funktion, um herauszufinden, ob eine Matrix einen bestimmten Wert enthält? (ala PHPs in_array())

Zenna
quelle
Beachten Sie bei Gleitkommadaten, bei denen eine Toleranz gewünscht sein kann, dass die Version R2015a neue Funktionen hinzugefügt hat, um dies mit einer einzigen integrierten Funktion zu handhaben. Die akzeptierten Lösungen für Daten mit ganzzahligen Werten sind großartig, aber für Floats springen Sie zu dieser Antwort . Entschuldigung für die Eigenwerbung, aber es ist eine große Ergänzung zu MATLAB, nachdem jahrelang gefragt wurde.
Chappjc

Antworten:

99

Viele Möglichkeiten, dies zu tun. ismember ist das erste, das mir in den Sinn kommt, da es sich um eine festgelegte Mitgliedschaftsaktion handelt, die Sie durchführen möchten. So

X = primes(20);
ismember([15 17],X)
ans =
      0    1

Da 15 keine Primzahl ist, aber 17, hat ismember hier seine Arbeit gut gemacht.

Natürlich funktioniert find (oder eines) auch. Aber diese sind nicht in dem Sinne vektorisiert, wie es das Mitglied war. Wir können testen, ob 15 in der durch X dargestellten Menge enthalten ist, aber um diese beiden Zahlen zu testen, wird eine Schleife oder aufeinanderfolgende Tests durchgeführt.

~isempty(find(X == 15))
~isempty(find(X == 17))

oder,

any(X == 15)
any(X == 17)

Abschließend möchte ich darauf hinweisen, dass Tests auf genaue Werte gefährlich sind, wenn die Zahlen echte Floats sein können. Tests gegen ganzzahlige Werte, wie ich gezeigt habe, sind einfach. Tests gegen Gleitkommazahlen sollten jedoch normalerweise eine Toleranz verwenden.

tol = 10*eps;
any(abs(X - 3.1415926535897932384) <= tol)

quelle
2
Der schnellste der drei scheint zu sein any. Aber vielleicht möchten Sie das selbst messen (mit ticund toc).
Lewistrick
Wenn Sie für Gleitkommawerte mindestens R2015a verwenden, verwenden Sie einfach ismembertol.
Chappjc
11

du kannst tun:

A = randi(10, [3 4]);      %# a random matrix
any( A(:)==5 )             %# does A contain 5?

Um dies oben auf vektorisierte Weise zu tun , verwenden Sie:

any( bsxfun(@eq, A(:), [5 7 11] )

oder wie @woodchips vorschlägt:

ismember([5 7 11], A)
Amro
quelle
Warum benutzt du [5 7 11] als Argument im November
Jordanien
1
@Jordan: Die zurückgegebene Antwort ist ein logisches Array (wahr / falsch) mit der gleichen Größe wie das Argument, das angibt, ob die Matrix Ajeden dieser Werte enthält (z. B. die [true, true, false]Bedeutung Aenthält die Werte 5und 7nicht 11).
Amro
1
@AnderBiguri: Hier sind einige Tests, die Sie vergleichen können: gist.github.com/amroamroamro/e66ac6a88b0692d995fd
Amro
3

Wenn Sie überprüfen müssen, ob sich die Elemente eines Vektors in einem anderen befinden, ist die beste Lösung ismemberdie in den anderen Antworten erwähnte.

ismember([15 17],primes(20))

Wenn Sie sich jedoch mit Gleitkommazahlen beschäftigen oder nur enge Übereinstimmungen wünschen (+ - 1000 ist ebenfalls möglich), ist die beste Lösung, die ich gefunden habe, die ziemlich effiziente Dateiaustauschübermittlung:ismemberf

Es gibt ein sehr praktisches Beispiel:

[tf, loc]=ismember(0.3, 0:0.1:1) % returns false 
[tf, loc]=ismemberf(0.3, 0:0.1:1) % returns true

Obwohl die Standardtoleranz normalerweise ausreichend sein sollte, bietet sie Ihnen mehr Flexibilität

ismemberf(9.99, 0:10:100) % returns false
ismemberf(9.99, 0:10:100,'tol',0.05) % returns true
Dennis Jaheruddin
quelle
2

Für Gleitkommadaten können Sie die neue ismembertolFunktion verwenden , mit der die Satzmitgliedschaft mit einer angegebenen Toleranz berechnet wird . Dies ähnelt der ismemberfFunktion im Dateiaustausch, ist jedoch jetzt in MATLAB integriert. Beispiel:

>> pi_estimate = 3.14159;
>> abs(pi_estimate - pi)
ans =
   5.3590e-08
>> tol = 1e-7;
>> ismembertol(pi,pi_estimate,tol)
ans =
     1
chappjc
quelle