Javascript includes einzelne Array Werte
bearbeitet von
Hallo ebody,
(1) Ein Konstrukt vom Typ `if (something === true)` lässt sich als `if (something)` verkürzen, wenn man weiß, dass `something` definitiv ein boolescher Wert ist. Beim Ergebnis von includes ist das der Fall.
Eine Abfrage auf `=== true` brauchst Du nur, wenn Du außer `true` auch truthy Werte (Siehe unser Wiki, "[Was ist Wahrheit](https://wiki.selfhtml.org/wiki/JavaScript/Objekte/Boolean#Was_ist_Wahrheit.3F)") bekommen könntest und diese nicht als true akzeptieren willst.
(2) Es gibt die so genannten [Quantor](https://de.wikipedia.org/wiki/Quantor)funktionen für Arrays, die ermitteln, ob ein Callback für mindestens ein Array-Element (`some`) oder für alle Array-Elemente (`every`) zutrifft. Die kannst Du statt der zusätzlichen Schleife nutzen, landest dann aber bei mehrfach geschachtelten Pfeilfunktionen. Für Mathematiker: `some` entspricht $$\exists$$ und `every` implementiert $$\forall$$.
(3) Ich würde Dir definitiv empfehlen, für den filter-Callback eine Funktion zu verwenden. Und zwar so, dass Du über eine Helfer-Funktion gehst, die die gesuchten Genres als Parameter erhält und eine Funktion zurückgibt, die als Callback genutzt wird. Die übergebenen Genres stehen dieser Callbackfunktion dann als Teil der gebildeten [Closure](https://wiki.selfhtml.org/wiki/JavaScript/Objekte/this#Closures) zur Verfügung.
Was unklar ist: Machst Du eine "UND" oder eine "ODER" Suche? Wenn ich Dir [ "Komödie", "Horror" ] vorgebe - suchst Du dann alle Horrorkomödien oder alles, was Horror oder Komödie ist? Anders gefragt: Brauchst Du `some` oder `every`? Aber man kann ja zwei Callback-Generatoren bereitstellen:
~~~js
function createFilterForAll(...genresToFind) {
// User hat Array übergeben - ... legt ein weiteres Array drumherum
if (Array.isArray(genresToFind[0]))
genresToFind = genresToFind[0];
return movie => genresToFind.every(genre => movie.genres.includes(genre));
}
function createFilterForSome(...genresToFind) {
// User hat Array übergeben - ... legt ein weiteres Array drumherum
if (Array.isArray(genresToFind[0]))
genresToFind = genresToFind[0];
return movie => genresToFind.some(genre => movie.genres.includes(genre));
}
movies.filter(filterForAll("Horror", "Komödie"));
movies.filter(filterForSome("Horror", "Komödie"));
~~~
Die isArray Abfrage ist drin, falls jemand `filterForAll(["Horror", "Komödie"])` aufruft - in dem Fall macht der [Rest-Parameter `...genresToFind`](https://wiki.selfhtml.org/wiki/JavaScript/Operatoren/Rest-_oder_Spread-Operator#Erstellung_von_Restparametern) ein weiteres Array drumherum, das entfernt werden muss.
"`every`" und "`some`" kennt sogar schon der IE, aber Rest-Parameter nicht. Wenn Du auch im IE funktionieren willst, musst Du statt Rest-Parametern das arguments Objekt verwenden (was aber kein Array ist, d.h. Du musst every und some als Schleife ausprogrammieren) oder einfach definieren, dass der User ein Array übergeben muss. Letzteres macht auch die isArray Prüfung obsolet.
Einen solchen Filter kannst Du - wenn das not tut - auch vorab erzeugen und speichern.
Mich persönlich würde jetzt noch triggern, dass die beiden Funktionen sich lediglich darin unterscheiden, ob sie mit `some` oder `every` suchen, und ich würde das vermutlich noch abstrahieren. Und in ein Objekt kapseln. Das wird dann aber schwerer verständlich. Aussehen täte es so:
~~~js
const createFilter = (function() {
function createFilter(genresToFind, quantor) {
// Durch ... kann ein Array of Array entstehen
if (Array.isArray(genresToFind[0]))
genresToFind = genresToFind[0];
return movie => quantor.call(
genresToFind,
movie => movie.genres.includes(genre));
}
return {
all(...genresToFind) {
return createFilter(genresToFind, Array.prototype.every);
},
some(...genresToFind) {
return createFilter(genresToFind, Array.prototype.some);
}
}
})();
movies.filter(createFilter.all("Horror", "Komödie"));
movies.filter(createFilter.some("Horror", "Komödie"));
~~~
Die Kurzschreibweise für Methoden in Objektliteralen kennt der IE nicht, dort bräuchtest Du
~~~js
return {
all: function() {
return createFilter(arguments, Array.prototype.every);
},
some: function() {
return createFilter(arguments, Array.prototype.some);
}
~~~
_Rolf_
--
sumpsi - posui - obstruxi