Quatre méthodes de recherche dans les tableaux en JavaScript

Il existe de nombreux moyens permettant de trouver des objets dans Arrays en JavaScript. Vous pouvez toujours recourir à la basique for pour boucler, mais avec l'ES6+, il existe de nombreuses méthodes pour boucler le tableau et trouver facilement ce dont vous avez besoin.

Avec autant de méthodes différentes, laquelle utilisez-vous et dans quel cas ? Par exemple, lorsque vous effectuez une recherche dans un tableau, voulez-vous savoir si l'élément se trouve dans le tableau ? Avez-vous besoin de l'index de l'élément ou de l'élément lui-même ?

Pour chaque méthode différente que nous aborderons, il est important de comprendre qu'il s'agit de méthodes intégrées au prototype Array. Cela signifie que vous devez simplement les enchaîner sur n'importe quel tableau avec la notation par points. Cela signifie également que ces méthodes ne sont pas disponibles sur les objets ou tout autre objet que les Arrays (bien qu'il y ait un chevauchement avec les Strings).

Nous allons examiner les méthodes Array suivantes :

  • Array.includes
  • Array.find
  • Array.indexOf
  • Array.filter

includes

const alligator = ["thick scales", 80, "4 foot tail", "rounded snout"];  alligator.includes("thick scales"); // returns true 

La méthode .includes() renvoie une valeur booléenne et est parfaite pour vous indiquer si un élément existe ou non dans un tableau. Elle vous offre simplement réponse true ou false. Ceci est la syntaxe de base :

arr.includes(valueToFind, [fromIndex]); 

Or, comme vous le voyez dans notre exemple, nous n'avions qu'un seul paramètre : la valeur ToFind. C'est la valeur à faire correspondre dans le tableau. L'optionnelle fromIndex est un nombre, indiquant à partir de quel index vous voulez commencer à chercher (la valeur par défaut est 0, donc le tableau entier est inspecté). Ainsi, puisque dans notre exemple, l'élément “thick scales” est à l'index 0, ce qui suit serait faux : alligator.includes('thick scales', 1) ; puisqu'il commence la recherche à partir de l'index 1 et plus.

Il y a toutefois quelques points importants à noter. Cette méthode .includes() utilise une comparaison stricte. Cela signifie, d'après l'exemple ci-dessus, que le résultat suivant serait faux : alligator.includes('80') ; en effet, si 80 == '80' est vrai, 80 === '80' est faux : les différents types ne se prêtent pas à une comparaison stricte.

find

En quoi .find() est-elle différente de la méthode includes() ? Si, dans notre exemple, nous ne modifions que le texte “includes” pour le remplacer par “find”, nous obtiendrons cette erreur :

Uncaught TypeError: thick scales is not a function 

C'est parce que la méthode find nécessite qu'une fonction soit admise. C'est parce que la méthode find ne va pas utiliser un simple opérateur de comparaison comme le fait “includes()”. À la place, il passera chaque élément dans votre fonction et verra si elle renvoie vrai ou faux. Donc, bien que cela fonctionne : alligator.find(() => 'thick scales');, vous voudrez probablement mettre votre propre opérateur de comparaison dans la fonction pour qu'elle renvoie tout ce qui est pertinent.

const alligator = ["thick scales", 80, "4 foot tail", "rounded snout"];  alligator.find(el => el.length < 12); // returns '4 foot tail' 

Cette fonction simple de notre méthode find examine chaque élément du tableau, avec l'alias “el” que nous lui avons attribué, et s'arrête lorsqu'elle trouve le premier élément qui est vrai. Dans notre cas, ce qui est vrai doit avoir une propriété de longueur inférieure à 12 (les nombres n'ont pas de propriété de longueur). Vous pouvez bien sûr rendre cette fonction aussi complexe que nécessaire, en faisant en sorte que votre condition true réponde à vos besoins.

Remarquez également que cela n'a pas été renvoyé comme true. La méthode find ne renvoie pas un booléen mais le premier élément correspondant. S'il n'y a pas d'élément correspondant – car il n'existe rien qui réponde aux critères définis dans votre fonction – elle renverra undefined. Notez également qu'elle renvoie le premier, donc s'il y a plus d'un élément dans le tableau qui répond aux critères, elle ne prendra que la première instance. Dans notre exemple, s'il y avait une autre chaîne de moins de 12 après “4 feet tall”, cela ne changerait pas notre résultat.

Dans notre exemple, nous avons utilisé le callback avec un paramètre seulement. Vous pouvez également ajouter des paramètres pour référencer l'index de l'élément en cours. L'ensemble du tableau lui-même peut être un autre paramètre mais je trouve que cela est rarement utilisé. Voici un exemple utilisant l'index :

alligator.find((el, idx) => typeof el === "string" && idx === 2); // returns '4 foot tall' 

Nous savons que, dans notre tableau, 3 éléments différents remplissent la première condition (typeof el === ‘string’). Si c'était notre seule condition, elle nous renverrait la première, “thick scales”. Mais la différence, c'est qu'un seul d'entre eux a un indice de 2 qui signifie “4 foot tall”.

En parlant d'index,.findIndex() est une méthode de tableau similaire. Cette méthode reçoit également une fonction, mais comme vous pouvez le deviner, elle renvoie l'index de l'élément correspondant au lieu de l'élément lui-même.

indexOf

const alligator = ["thick scales", 80, "4 foot tail", "rounded snout"];  alligator.indexOf("rounded snout"); // returns 3 

De la même manière que la méthode .includes(), la méthode .indexOf() utilise une comparaison stricte et non une fonction comme nous l'avons vu avec la méthode .find(). Cependant, contrairement à includes(), elle renvoie l'index de l'élément plutôt qu'un booléen. Vous pouvez également indiquer à partir de quel index du tableau la recherche doit débuter.

Je trouve la méthode indexOf() très utile. Elle est simple et rapide, peut vous dire où se trouve l'élément dans le tableau et peut également vous dire si l'élément existe. Comment vous indique-t-elle si l'élément existe ? Fondamentalement, nous pouvons savoir que l'élément existe si elle renvoie un nombre positif ; si elle renvoie -1, nous savons que l'élément n'existe pas.

alligator.indexOf("soft and fluffy"); // returns -1 alligator.indexOf(80); // returns 1 alligator.indexOf(80, 2); // returns -1 

Et comme vous pouvez le voir, bien que nous aurions pu utiliser les méthodes find() ou findIndex() pour obtenir les mêmes informations, celle-ci est beaucoup moins longue à écrire. Nous n'avons pas besoin d'écrire une fonction pour la comparaison, car elle se trouve déjà dans la méthode indexOf.

Cependant, comme les autres, indexOf() renvoie également l'index du premier élément correspondant qu'elle trouve. JavaScript nous donne une méthode de tableau alternative .lastIndexOf(). Comme vous pouvez le deviner, elle fait la même chose que indexOf() mais en partant du dernier index du tableau et en travaillant à rebours. Vous pouvez également spécifier un second paramètre, mais n'oubliez pas que les index ne changent pas simplement parce que vous utilisez une méthode différente.

const alligator = ["thick scales", 80, "4 foot tail", "rounded snout", 80];  alligator.indexOf(80); // returns 1 alligator.lastIndexOf(80); // returns 4 alligator.indexOf(80, 2); // returns 4 alligator.lastIndexOf(80, 4); // returns 4 alligator.lastIndexOf(80, 3); // returns 1 

Bonus : filter

const alligator = ["thick scales", 80, "4 foot tail", "rounded snout", 80];  alligator.filter(el => el === 80); //returns [80, 80] 

La méthode filter() est semblable à la méthode find(), en ce sens qu'elle nécessite une fonction passée et une condition pour ce qui sera renvoyé. La principale différence est que filter() renvoie toujours un tableau, même s'il n'y a qu'un seul élément correspondant. Mais elle renvoie tous les éléments correspondants, alors que find() ne renvoie que la première correspondance.

La chose importante à savoir sur la méthode filter est qu'elle renvoie tous les éléments correspondant à vos critères. Cela ne concerne peut-être que moi, mais il est probable que je m'emmêle les pinceaux en pensant “ce sont les éléments que je veux filtrer en out”, alors qu'en vérité, vous indiquez les éléments que vous souhaitez filtrer en in.

Conclusion

D'après moi, la méthode la plus simple à utiliser quand on cherche quelque chose, est la méthode find(), mais comme vous pouvez le voir, cela dépend vraiment de votre cas.

  • Vous avez uniquement besoin de savoir si l'élément existe ? Dans ce cas, utilisez .includes().
  • Vous avez besoin d'obtenir l'élément lui-même ? Utilisez .find() ou .filter() pour plusieurs éléments.
  • Vous avez besoin de trouver l'index de l'élément ? Dans ce cas, utilisez .indexOf() ou findIndex() pour une recherche plus complexe.

Les tableaux présentés dans les exemples ci-dessus étaient très simples. Vous pourriez vous retrouver avec un tableau d'objects. Voici quelques exemples très simples pour naviguer dans la jungle des objets imbriqués :

const jungle = [   { name: "frog", threat: 0 },   { name: "monkey", threat: 5 },   { name: "gorilla", threat: 8 },   { name: "lion", threat: 10 } ];  // break the object down in order to use .includes() or .indexOf() const names = jungle.map(el => el.name); // returns ['frog', 'monkey', 'gorilla', 'lion'] console.log(names.includes("gorilla")); // returns true console.log(names.indexOf("lion")); // returns 3 - which corresponds correctly assuming no sorting was done  // methods we can do on the array of objects console.log(jungle.find(el => el.threat == 5)); // returns object - {name: "monkey", threat: 5} console.log(jungle.filter(el => el.threat > 5)); // returns array - [{name: "gorilla", threat: 8}, {name: 'lion', threat: 10}]