Nous vous présentons une traduction d'un article de Thomas Lombart, qui a été publié sur medium.freecodecamp.org. La traduction est publiée avec la permission de l'auteur.
Un exemple d'utilisation de la méthode de réduction pour réduire un tableauPermettez-moi de faire une déclaration audacieuse: les boucles sont souvent inutiles et rendent le code difficile à lire. Pour les itérations dans les tableaux, la recherche, le tri des éléments et d'autres actions similaires, vous pouvez utiliser l'une des méthodes ci-dessous.
Malgré leur efficacité, la plupart de ces méthodes sont encore peu connues et peu populaires. Je ferai le travail dur pour vous et parlerai des plus utiles. Lisez cet article comme guide des méthodes de tableau JavaScript.
Remarque : Avant de commencer, vous devez savoir une chose: je suis partisan de la programmation fonctionnelle. Pour éviter les effets secondaires, je m'efforce d'appliquer des méthodes qui ne modifient pas directement le tableau d'origine. Je ne vous dis pas de refuser de changer le tableau du tout, mais il vaut la peine de considérer que certaines méthodes y mènent. En conséquence, des effets secondaires, des modifications indésirables et, par conséquent, des bogues apparaissent.
Cet article a été initialement publié sur
thomlom.dev , où vous pouvez trouver plus de matériel de développement Web.
Les bases
Il existe quatre méthodes à savoir si vous travaillez avec des tableaux. Ce sont la
map
, le
filter
, la
reduce
et l'opérateur de
spread
. Ils sont efficaces et utiles.
carteVous utiliserez souvent la méthode de la
map
. En général, chaque fois que vous devez modifier les éléments d'un tableau, envisagez cette option.
Il prend un paramètre - une fonction qui est appelée sur chaque élément du tableau, puis retourne un
nouveau tableau afin qu'il n'y ait pas d'effets secondaires.
const numbers = [1, 2, 3, 4] const numbersPlusOne = numbers.map(n => n + 1) console.log(numbersPlusOne)
Vous pouvez également créer un nouveau tableau qui stocke une seule propriété spécifique de l'objet.
const allActivities = [ { title: 'My activity', coordinates: [50.123, 3.291] }, { title: 'Another activity', coordinates: [1.238, 4.292] } ] const allCoordinates = allActivities.map(activity => activity.coordinates) console.log(allCoordinates)
Alors, souvenez-vous: lorsque vous devez
modifier un tableau, pensez à utiliser la
carte .
filtrerLe nom de cette méthode parle de lui-même: utilisez-le lorsque vous souhaitez filtrer un tableau.
Comme
map
, le
filter
prend comme paramètre unique une fonction qui est appelée sur chaque élément du tableau. Cette fonction doit renvoyer une valeur booléenne:
true
- si vous souhaitez enregistrer l' élément dans un tableau;false
- si vous ne souhaitez pas l'enregistrer.
En conséquence, vous aurez le nouveau tableau correct avec les éléments que vous souhaitez laisser.
Par exemple, seuls les nombres impairs peuvent être stockés dans un tableau.
const numbers = [1, 2, 3, 4, 5, 6] const oddNumbers = numbers.filter(n => n % 2 !== 0) console.log(oddNumbers)
Vous pouvez également utiliser un filtre pour supprimer un élément spécifique du tableau.
const participants = [ { id: 'a3f47', username: 'john' }, { id: 'fek28', username: 'mary' }, { id: 'n3j44', username: 'sam' }, ] function removeParticipant(participants, id) { return participants.filter(participant => participant.id !== id) } console.log(removeParticipant(participants, 'a3f47'))
réduireÀ mon avis, cette méthode est la plus difficile à comprendre. Mais dès que vous le maîtriserez, vous aurez un tas d'opportunités.
En règle générale, la méthode de
reduce
prend un tableau de valeurs et les concatène en une seule valeur. Il prend deux paramètres, une fonction de rappel (qui est le
réducteur ) et une valeur initiale facultative (qui est le premier élément du tableau par défaut). La boîte de vitesses elle-même prend quatre paramètres:
- une batterie qui recueille les valeurs renvoyées dans la boîte de vitesses ;
- valeur actuelle du tableau;
- indice actuel;
- le tableau pour lequel la méthode de
reduce
été appelée.
Fondamentalement, vous n'utiliserez que les deux premiers paramètres - la batterie et la valeur actuelle.
Mais n'allons pas au fond de la théorie et considérons l'exemple le plus courant de l'application de la
reduce
.
const numbers = [37, 12, 28, 4, 9] const total = numbers.reduce((total, n) => total + n) console.log(total)
Dans la première itération, l'accumulateur, qui est la somme, prend la valeur initiale 37. La valeur retournée est 37 + n, où n = 12. On obtient 49.
Lors de la deuxième itération, l'accumulateur est 49, la valeur retournée est 49 + 28 = 77. Et ainsi de suite.
La méthode de
reduce
est tellement fonctionnelle que vous pouvez l'utiliser pour créer de nombreuses méthodes de tableau comme la
map
ou le
filter
.
const map = (arr, fn) => { return arr.reduce((mappedArr, element) => { return [...mappedArr, fn(element)] }, []) } console.log(map([1, 2, 3, 4], n => n + 1))
En règle générale, nous attribuons la valeur initiale
[]
à la méthode de
reduce
- l'accumulateur. Pour la
map
nous exécutons une fonction dont le résultat est ajouté à la fin de la batterie en utilisant
l'opérateur de propagation (nous en parlerons ci-dessous, ne vous inquiétez pas). Pour le
filter
faisons presque la même chose, nous exécutons uniquement la fonction de filtre sur l'élément. Si c'est vrai, nous retournons le tableau
précédent . Sinon, ajoutez l'élément à la fin du tableau.
Regardons un exemple plus complexe: réduisez considérablement le tableau
[1, 2, 3, [4, [[[5, [6, 7]]]], 8]]
à
[1, 2, 3, 4, 5, 6, 7, 8]
.
function flatDeep(arr) { return arr.reduce((flattenArray, element) => { return Array.isArray(element) ? [...flattenArray, ...flatDeep(element)] : [...flattenArray, element] }, []) } console.log(flatDeep([1, 2, 3, [4, [[[5, [6, 7]]]], 8]]))
Cet exemple est très similaire à
map
, sauf que nous utilisons ici la récursivité. Je ne m'attarderai pas sur la récursivité en détail, car cela dépasse la portée de notre sujet, mais si vous voulez en savoir plus, allez à cette
excellente ressource .
Déclaration de propagation (ES2015)Je suis d'accord, ce n'est pas une méthode. Cependant, l'opérateur d'étalement aide à atteindre différents objectifs lors de l'utilisation de tableaux. Vous pouvez l'appliquer pour développer les valeurs d'un tableau dans un autre, puis faire une copie ou lier plusieurs tableaux ensemble.
const numbers = [1, 2, 3] const numbersCopy = [...numbers] console.log(numbersCopy)
Remarque : l'instruction spread crée une
copie superficielle du tableau d'origine. Mais que signifie «superficiel»?
Une telle copie dupliquera le moins possible les éléments originaux. Si vous avez un tableau avec des nombres, des chaînes ou des valeurs booléennes (
types primitifs ), il n'y a aucun problème et les valeurs sont vraiment dupliquées. Cependant, les choses sont différentes avec les
objets et les
tableaux : seule une
référence à la valeur d'origine est copiée. Par conséquent, si vous effectuez une copie superficielle du tableau comprenant l'objet et modifiez l'objet dans le tableau copié, il sera également modifié dans l'original, car ils ont la
même référence .
const arr = ['foo', 42, { name: 'Thomas' }] let copy = [...arr] copy[0] = 'bar' console.log(arr)
Donc, si vous souhaitez créer une copie réelle d'un tableau qui contient un objet ou des tableaux, vous pouvez utiliser une fonction
lodash comme
cloneDeep . Mais ne vous considérez pas obligé de le faire. Votre objectif est de
découvrir comment tout fonctionne sous le capot .
Méthodes utiles
Vous trouverez ci-dessous d'autres méthodes qui sont également utiles à connaître et qui peuvent être utiles pour résoudre des problèmes tels que la recherche d'un élément dans un tableau, la suppression d'une partie d'un tableau, et bien plus encore.
comprend (ES2015)Avez-vous déjà utilisé
indexOf
pour savoir s'il y a un élément dans un tableau ou non? Une terrible façon de vérifier, non?
Heureusement, la méthode
includes
effectue la validation pour nous. Définissez le paramètre pour includes, et il recherchera l'élément dans le tableau.
const sports = ['football', 'archery', 'judo'] const hasFootball = sports.includes('football') console.log(hasFootball)
concatLa méthode concat peut être utilisée pour fusionner deux tableaux ou plus.
const numbers = [1, 2, 3] const otherNumbers = [4, 5, 6] const numbersConcatenated = numbers.concat(otherNumbers) console.log(numbersConcatenated)
forEachSi vous souhaitez effectuer une action pour chaque élément du tableau, vous pouvez utiliser la méthode
forEach
. Il prend une fonction comme paramètre, qui à son tour prend également trois paramètres: valeur actuelle, index et tableau.
const numbers = [1, 2, 3, 4, 5] numbers.forEach(console.log)
indexOfCette méthode est utilisée pour renvoyer le premier index auquel l'élément peut être trouvé dans le tableau. De plus,
indexOf
vérifie souvent la présence d'un élément dans un tableau. Honnêtement, maintenant je l'utilise rarement.
const sports = ['football', 'archery', 'judo'] const judoIndex = sports.indexOf('judo') console.log(judoIndex)
trouverLa méthode de
find
est similaire au
filter
. Vous devez lui fournir une fonction qui teste chaque élément du tableau. Cependant,
find
arrête de tester les éléments dès qu'il en trouve un qui a réussi le test. Ce n'est
pas un filter
qui itère sur l'ensemble du tableau quelles que soient les circonstances.
const users = [ { id: 'af35', name: 'john' }, { id: '6gbe', name: 'mary' }, { id: '932j', name: 'gary' }, ] const user = users.find(user => user.id === '6gbe') console.log(user)
Par conséquent, utilisez la méthode de
filter
lorsque vous souhaitez filtrer l'
intégralité du tableau et la méthode
find
lorsque vous êtes sûr de rechercher un élément
unique dans le tableau.
findIndexCette méthode est presque identique à
find
, mais elle retourne l'index du premier élément trouvé au lieu de l'élément lui-même.
const users = [ { id: 'af35', name: 'john' }, { id: '6gbe', name: 'mary' }, { id: '932j', name: 'gary' }, ] const user = users.findIndex(user => user.id === '6gbe') console.log(user)
Vous pourriez penser que
findIndex
et
indexOf
sont la même chose. Pas vraiment. Le premier paramètre d'
indexOf
est une valeur primitive (une valeur booléenne, un nombre, une chaîne, une valeur non définie ou un caractère), tandis que le premier paramètre,
findIndex
est une fonction de rappel.
Par conséquent, lorsque vous devez rechercher l'index d'un élément dans un tableau de valeurs primitives, vous pouvez travailler avec
indexOf
. Si vous avez des éléments plus complexes, tels que des objets, utilisez
findIndex
.
trancheLorsque vous devez faire partie d'un tableau ou copier un tableau, vous pouvez vous référer à la méthode
slice
. Mais attention: comme l'opérateur spread,
slice
renvoie une
copie superficielle .
const numbers = [1, 2, 3, 4, 5] const copy = numbers.slice()
Au début de l'article, j'ai mentionné que les boucles sont souvent inutiles. Permettez-moi de vous montrer comment vous en débarrasser.
Supposons que vous souhaitiez renvoyer un certain nombre de messages de discussion à partir de l'API et que vous n'en ayez besoin que de cinq. Voici deux approches: une avec des boucles, l'autre avec une méthode de
slice
.
certainsSi vous souhaitez vérifier si
au moins un élément du tableau réussit le test, vous pouvez en utiliser. Comme
map
,
filter
ou
find
, la méthode
some
prend une fonction de rappel comme seul paramètre, puis retourne
true
si au moins un élément réussit la vérification, et
false
sinon.
some
conviennent également pour travailler avec des autorisations.
const users = [ { id: 'fe34', permissions: ['read', 'write'], }, { id: 'a198', permissions: [], }, { id: '18aa', permissions: ['delete', 'read', 'write'], } ] const hasDeletePermission = users.some(user => user.permissions.includes('delete') ) console.log(hasDeletePermission)
tousCette méthode est similaire à
some
, sauf qu'elle vérifie que
chaque élément (et
non un ) correspond à la condition.
const users = [ { id: 'fe34', permissions: ['read', 'write'], }, { id: 'a198', permissions: [], }, { id: '18aa', permissions: ['delete', 'read', 'write'], } ] const hasAllReadPermission = users.every(user => user.permissions.includes('read') ) console.log(hasAllReadPermission)
plat (ES2019)Ce sont des méthodes complètement nouvelles dans le monde JavaScript. Habituellement,
flat
crée un nouveau tableau, connectant tous les éléments d'un tableau imbriqué. Il prend un paramètre - un nombre qui indique combien vous voulez réduire la dimension du tableau.
const numbers = [1, 2, [3, 4, [5, [6, 7]], [[[[8]]]]]] const numbersflattenOnce = numbers.flat() console.log(numbersflattenOnce)
flatMap (ES2019)Devinez ce que fait cette méthode? Je parie que vous comprendrez un nom.
Tout d'abord, il exécute la fonction de mappage pour chaque élément, puis réduit le tableau à la fois. C'est aussi simple que ça!
const sentences = [ 'This is a sentence', 'This is another sentence', "I can't find any original phrases", ] const allWords = sentences.flatMap(sentence => sentence.split(' ')) console.log(allWords)
Dans cet exemple, vous avez plusieurs phrases dans le tableau et vous souhaitez obtenir tous les mots. Au lieu d'utiliser la méthode
map
et de diviser toutes les phrases en mots, puis de raccourcir le tableau, vous pouvez utiliser
flatMap
tout de
flatMap
.
Ensuite, vous pouvez compter le nombre de mots avec la fonction de
reduce
(cela ne s'applique pas à
flatMap
, je veux juste vous montrer un autre exemple d'utilisation de la méthode de
reduce
).
const wordsCount = allWords.reduce((count, word) => { count[word] = count[word] ? count[word] + 1 : 1 return count }, {}) console.log(wordsCount)
La méthode
flatMap
également souvent utilisée en programmation réactive. Vous pouvez voir un exemple
ici .
rejoindreSi vous devez créer une chaîne basée sur des éléments de tableau, la méthode de
join
est ce dont vous avez besoin. Il vous permet de créer une nouvelle ligne en connectant tous les éléments du tableau, séparés par le séparateur fourni.
Par exemple, à l'aide de la
join
vous pouvez afficher visuellement tous les participants d'une activité.
const participants = ['john', 'mary', 'gary'] const participantsFormatted = participants.join(', ') console.log(participantsFormatted)
Et ceci est un exemple plus réaliste où vous pouvez d'abord filtrer les participants et obtenir leurs noms.
const potentialParticipants = [ { id: 'k38i', name: 'john', age: 17 }, { id: 'baf3', name: 'mary', age: 13 }, { id: 'a111', name: 'gary', age: 24 }, { id: 'fx34', name: 'emma', age: 34 }, ] const participantsFormatted = potentialParticipants .filter(user => user.age > 18) .map(user => user.name) .join(', ') console.log(participantsFormatted)
deIl s'agit d'une méthode
statique qui crée un nouveau tableau à partir d'un objet de type tableau ou itérable, tel qu'une chaîne. Il peut être utile lorsque vous travaillez avec le modèle d'objet de document.
const nodes = document.querySelectorAll('.todo-item')
Avez-vous vu que nous avons utilisé un type de tableau au lieu d'une instance de tableau? C'est pourquoi cette méthode est appelée statique.
Ensuite, vous pouvez vous amuser avec les nœuds, par exemple en enregistrant des écouteurs d'événements pour chacun d'eux en utilisant la méthode
forEach
.
todoItems.forEach(item => { item.addEventListener('click', function() { alert(`You clicked on ${item.innerHTML}`) }) })
Modification de tableau à connaître
Voici d'autres méthodes standard. Leur différence est qu'ils modifient le tableau d'origine. Il n'y a rien de mal à ce changement, mais vous devez en tenir compte lorsque vous travaillez.
Si vous ne souhaitez pas modifier le tableau d'origine tout en travaillant avec ces méthodes, faites une surface ou une copie complète à l'avance.
const arr = [1, 2, 3, 4, 5] const copy = [...arr]
trierOui,
sort
modifie le tableau d'origine. En fait, il trie les éléments du tableau en place. La méthode de tri par défaut transforme tous les éléments en chaînes et les trie par ordre alphabétique.
const names = ['john', 'mary', 'gary', 'anna'] names.sort() console.log(names)
Soyez prudent: si vous, par exemple, êtes passé du langage Python, la méthode de
sort
lorsque vous travaillez avec un tableau de nombres ne vous donnera pas le résultat souhaité.
const numbers = [23, 12, 17, 187, 3, 90] numbers.sort() console.log(numbers)
Comment alors trier un tableau? La méthode de
sort
prend une fonction -
une fonction de comparaison . Il prend deux paramètres: le premier élément (
) et le deuxième élément pour la comparaison (
b
). La comparaison entre ces deux éléments nécessite un retour de chiffres:
- si la valeur est négative -
a
trié avant b
; - si la valeur est positive,
b
trié avant a
; - si la valeur est 0, aucun changement.
Ensuite, vous pouvez trier les chiffres.
const numbers = [23, 12, 17, 187, 3, 90] numbers.sort((a, b) => a - b) console.log(numbers)
Ou vous pouvez trier les dates les plus récentes.
const posts = [ { title: 'Create a Discord bot under 15 minutes', date: new Date(2018, 11, 26), }, { title: 'How to get better at writing CSS', date: new Date(2018, 06, 17) }, { title: 'JavaScript arrays', date: new Date() }, ] posts.sort((a, b) => a.date - b.date)
remplirLa méthode
fill
modifie ou remplit tous les éléments du tableau de l'index de début à la fin avec la valeur spécifiée. Un exemple de l'excellente utilisation de
fill
est de remplir un nouveau tableau avec les données initiales.
inverserIl me semble que le nom de la méthode explique pleinement son essence.
const numbers = [1, 2, 3, 4, 5] numbers.reverse() console.log(numbers)
popCette méthode supprime le dernier élément du tableau et le renvoie.
const messages = ['Hello', 'Hey', 'How are you?', "I'm fine"] const lastMessage = messages.pop() console.log(messages)
Méthodes pouvant être remplacées
Dans la dernière section, vous trouverez des méthodes qui modifient le tableau d'origine et qui sont faciles à trouver une alternative. Je ne dis pas qu'ils doivent être réduits, je veux simplement vous dire que certaines méthodes ont des effets secondaires et peuvent être remplacées.
pousserCette méthode est fréquemment utilisée. Il vous permet d'ajouter un ou plusieurs éléments au tableau, ainsi que de créer un nouveau tableau basé sur le précédent.
const todoItems = [1, 2, 3, 4, 5] const itemsIncremented = [] for (let i = 0; i < items.length; i++) { itemsIncremented.push(items[i] + 1) } console.log(itemsIncremented)
Si vous devez créer un tableau sur la base d'un autre, comme dans la méthode
itemsIncremented
, il existe des
filter
map
, de
filter
ou de
reduce
appropriés qui nous sont déjà familiers. Par exemple, nous pouvons prendre la
map
pour ce faire.
const itemsIncremented = todoItems.map(x => x + 1)
Et si vous souhaitez utiliser
push
lorsque vous devez ajouter un nouvel élément, alors l'opérateur d'étalement est utile.
const todos = ['Write an article', 'Proofreading'] console.log([...todos, 'Publish the article'])
épissuresplice
souvent accessible pour nettoyer un élément à un index spécifique. Vous pouvez faire de même avec la méthode de
filter
.
const months = ['January', 'February', 'March', 'April', ' May']
Vous pouvez demander: et si je dois supprimer un grand nombre d'éléments? Ensuite, utilisez une
slice
.
const months = ['January', 'February', 'March', 'April', ' May']
décalerLa méthode
shift
supprime le premier élément du tableau et le renvoie. Pour ce faire, dans le style de la programmation fonctionnelle, vous pouvez utiliser l'instruction spread ou rest.
const numbers = [1, 2, 3, 4, 5]
décalerLa méthode unshift vous permet d'ajouter un ou plusieurs éléments au début d'un tableau. Comme
shift
, vous pouvez le faire avec l'opérateur spread.
const numbers = [3, 4, 5]
TL; DR
- Lorsque vous souhaitez effectuer certaines opérations avec un tableau, n'utilisez pas la boucle for et ne réinventez pas la roue, car il existe très probablement une méthode ci-dessus qui peut faire ce dont vous avez besoin.
- Le plus souvent, vous utiliserez la
map
, le filter
, reduce
méthodes de reduce
et l'opérateur de propagation - ce sont des outils importants pour tout développeur. - Il existe également de nombreuses méthodes de tableau qu'il serait bon de connaître:
slice
, some
, flatMap
, etc. Apprenez à les connaître et appliquez si nécessaire. - Les effets secondaires peuvent entraîner des changements indésirables. N'oubliez pas que certaines méthodes modifient votre tableau d'origine.
- La méthode de
slice
et l'opérateur d'étalement font des copies superficielles. Par conséquent, les objets et les sous-réseaux auront les mêmes liens - cela vaut également la peine d'être gardé à l'esprit. - Les anciennes méthodes qui modifient le tableau peuvent être remplacées par de nouvelles. Vous décidez quoi faire.
Vous savez maintenant tout ce que vous devez savoir sur les tableaux JavaScript. Si vous avez aimé
cet article , cliquez sur le bouton "Pat" (jusqu'à 50 fois, si vous voulez :-)) et partagez-le. Et n'hésitez pas à partager vos impressions dans les commentaires!