Frage zu Rückgabewerten von filter() bzw. find()
Pep
- javascript
Hallo,
Okay, nicht wirklich eine Frage. ...eher eine Spielerei, quasi für hier anwesende Javascript Nerds wie mich :)
Es sei angemerkt, alles "funktioniert", folgendes also eine REINE Verständnisfrage:
Bin in meinem Code über die Situation gestolpert, dass ich aus einem Array "arr" mit Buchstaben von "a" bis "z" alle Konsonanten herausfiltern wollte. Dazu habe ich ein Array
const vowels = ["a", "e", "i", "o", "u"];
geschaffen und dann die Konsonanten wie folgt gefiltert:
// BEWEISSTÜCK 1
const consonants = arr.filter(cur => !vowels.find(el => el === cur));
Gleichsam ließen sich natürlich die Vokale filtern:
// BEWEISSTÜCK 2
const newVowels = arr.filter(cur => vowels.find(el => el === cur)); // "vowels" vs "newVowels" - SÄMTLICHE Naming Conventions out the window :O
NUN ZUR EIGENTLICHEN FRAGE!:
WARUM funktioniert das eigentlich?
filter() siebt alle als "true" zurückgegebenen Werte aus. find() hingegen liefert ja NICHT explizit "true" oder "false", sondern den ersten gefundenen Wert, BZW.(!) "undefined", wenn kein Wert gefunden wurde. BEWEISSTÜCK 1 lässt sich daher übersetzen als
const consonants = arr.filter(cur => !undefined); // Konsonanten werden in vowels ja nicht gefunden!
"!undefined" === "true", daher soweit alles gut
BEWEISSTÜCK 2 aber gibt ja nicht explizit true zurück, sondern den ersten Wert, der ein Match ergibt, daher
const newVowels = arr.filter(cur => "a"); // bzw. "e", "i",... je nach Wert von "cur", hier ist "cur" "a"
Warum wird hier der zurückgegebene Vokal (in diesem Beispiel bei diesem Durchgang "a") als "true" von filter() interpretiert?
Wie beschrieben... Spielerei... trotzdem danke!
Pep
Hallo Pep,
Diese Frage stellte schon Pilatus...
Was ist Wahrheit? - er hatte allerdings größere Probleme mit der Antwort als wir hier 😉.
Rolf
Jetzt bin ich restlos verwirrt und stehe HEMMUNGSLOST auf der Leitung.
console.log("a" == true);
ergibt FALSE
In vorigem Beispiel [BEWEISSTÜCK 2] ist "a" aber truthy
const newVowels = arr.filter(cur => "a");
Oder höflich ausgedrückt: HÄH?!
Hi,
console.log("a" == true);
ergibt FALSE
hier wird m.E. einer der beiden Operanden (vermutlich der zweite) typ-konvertiert, damit er zum anderen paßt (die genauen Regeln weiß ich nicht auswendig), und dann erst verglichen.
In vorigem Beispiel [BEWEISSTÜCK 2] ist "a" aber truthy
const newVowels = arr.filter(cur => "a");
Hier wird direkt von "a" die truthiness ausgewertet.
cu,
Andreas a/k/a MudGuard
Hallo MudGuard,
Das sind die Feinheiten bei denen ich auch erstmal grübeln muss.
Du dürftest aber recht haben, die type coercion müsste zum allgemeineren Typ hin verlaufen und deshalb "a"==true
gleichbedeutend sein mit "a"=="true"
.
Edit: Das war falsch und das Minus wohlverdient. Die Coercion liefert NaN == 1. Siehe den späteren Beitrag.
Rolf
Hallo, okay, bin hier wohl auf des Pudels Kern gestoßen.
== lässt wohl Vergleiche unabhängig des Typs zu, indem es eine Nicht-Nummer in eine Nummer umwandelt
10 == '10' // ==> 10 == 10 // ==> TRUE
true == 1 // ==> 1 == 1 // TRUE
true == 'true' // ==> 1 == NaN // FALSE
Hier muss es aber wohl eine andere Regel für Strings geben ....(?)
Hallo,
bin hier wohl auf des Pudels Kern gestoßen.
== lässt wohl Vergleiche unabhängig des Typs zu, indem es eine Nicht-Nummer in eine Nummer umwandelt
so lässt es der verlinkte Beitrag vermuten. Aber er unterschlägt ein wichtiges Detail.
10 == '10' // ==> 10 == 10 // ==> TRUE true == 1 // ==> 1 == 1 // TRUE true == 'true' // ==> 1 == NaN // FALSE
Hier muss es aber wohl eine andere Regel für Strings geben ....(?)
Warum? Welche?
Solange die beiden Operanden vom gleichen Typ sind, wird natürlich nichts konvertiert, sonst wäre ein Stringvergleich ja prinzipiell nicht möglich. Genau das erwähnt der Artikel nicht - vermutlich weil es selbstverständlich ist.
Einen schönen Tag noch
Martin
Hallo Pep,
wie ich schon schrieb, das sind Feinheiten die man nicht unbedingt im Kopf hat. Ich habe dazu nochmal recherchiert und update das Wiki dementsprechend (hier, ist aber noch nicht gespeichert).
Der Fall "a" == true
löst sich so auf:
⇒ "a" == 1
"a"
→ NaN
⇒ NaN == 1
⇒ false
Man sagt oft, dass die beiden folgenden if gleichwertig sind:
if (a) { ... }
if (a == true) { ... }
Nein, nicht in JavaScript. Der erste if-Block wird für jeden Wert ausführt, der truthy ist. Der zweite if-Block dagegen nur für diejenigen a, für die Number(a)
die Zahl 1 ergibt.
Gleichwertig sind dagegen diese Abfragen:
if (a) { ... }
if (!!a == true) { ... }
if (!!a === true) { ... }
if (Boolean(a) == true) { ... }
if (Boolean(a) === true) { ... }
Im Zeile 2 und 3 sorgt die doppelte Negation von a
dafür, dass jedes a
, das truthy ist, zu true
wird.
In Zeile 4 und 5 konvertiert die Boolean
-Funktion jeden falsy-Wert zu false
und den Rest zu true
. Damit klappt es auch.
Und weil mit !!
bzw. Boolean
dafür gesorgt wird, dass aus truthy true
wird, ist es dann auch egal, ob man ==
oder ===
verwendet.
Die entsprechenden PHP Regeln habe ich jetzt noch nicht studiert. Sie sind vermutlich in feinen, aber gemeinen Details anders.
Verwende nicht .find(), sondern .some() oder besser noch .includes(). Die liefern true oder false zurück und du hast die Frage nach der echten Wahrheit nicht mehr zu klären. Mit .includes hast Du noch den Vorteil, dass Du keine geschachtelte Callback-Funktion brauchst.
Rolf