Comprendre la réduction de tableau de JavaScript

Array reduction est une fonction pré-construite en JavaScript connue pour dérouter les nouveaux développeurs. Décomposons-le ensemble.
JavaScript est rempli de fonctions prédéfinies étonnantes pour manipuler des objets et des tableaux. En avez-vous déjà maîtrisé certains comme Array.map
ou Array.filter
? Qu'en est-il de l'insaisissable Array.reduce
?
Array Réduire en particulier peut être un peu compliqué pour les nouveaux développeurs. Je me souviens quand j'ai commencé à apprendre les fonctions du manipulateur de tableau. Filtre
bien sûr – c'était parfaitement logique. La carte
était un peu plus déroutante, mais après avoir suivi un exemple de code, il a cliqué. Mais réduire? Boi o boi. : D
En frappant MDN, vous êtes giflé par cette description.
La méthode reduction () exécute une fonction de réduction (que vous fournissez) sur chaque élément du tableau, ce qui donne un seul
En parcourant le document, vous êtes plongé dans des termes comme accumulateur
sans aucune explication – non non. Alors, sans plus tarder, parcourons celui-ci avec des exemples qui n'ont guère de sens, mais qui vous aident en fait à apprendre des choses. billes = []. Au début, votre sac est vide, mais vous voulez y ranger des billes, alors vous marbles.poussez (3)
des billes dedans. Ce sac a de nombreuses poches à l'intérieur, donc après avoir ajouté quelques billes et regardé à l'intérieur, vous voyez [3, 5, 1]
.
L'objectif est maintenant de trouver un moyen de les compter. Nous voulons réduire
tout ce sac (tableau) en une seule valeur – un compte
de nos billes.
Lorsque vous commencez à compter vos billes, vous faites une pile pour accumulez
ou regroupez ceux que vous avez déjà comptés. De cette façon, nous pouvons nous assurer de ne pas compter deux fois la même poche.
Essayons de mettre toute cette explication au code.
const billes = []
billes . pousser ( 3 )
billes . pousser ( 5 )
billes . pousser ( 1 )
console . journal ( billes )
const marbreCount = billes . réduire ([19659017] ( count value index ) => {
console . log ( `Index actuel: $ { index } ` )
const totalSoFar = valeur +
console . log ( `Ajout de $ { value } billes à notre décompte: $ { count } . Maintenant, nous obtenons: $ { totalSoFar } ` )
return totalSoFar
} )
console . log ( `Marble count: $ { marbreCount } ` )
Passons en revue cela lentement, car cela peut être un peu déroutant. Tout d'abord, nous créons le tableau
qui contiendra nos billes, et nous les ajoutons à différents index en utilisant le tableau push
.
Nous appelons marbles.reduce
, qui prend une fonction
comme premier paramètre. Cette fonction prend trois paramètres: le compte
(également appelé accumulateur
), la valeur
et l'indice
. Ce dernier est optionnel.
Le compte
sera le nombre de billes que nous avons compté JUSQU'À présent. Cela signifie qu'il augmentera chaque fois que nous passerons par la fonction. Il commencera avec la valeur de billes [0]
donc 3
.
La valeur
contiendra la valeur de l'indice suivant dans la boucle. La fonction réduire
passera par chacune d'elles SAUF pour l'index [0] – rappelez-vous, nous l'obtenons gratuitement dès le premier compte
.
L'index
] est l'indice actuel du tableau en cours de réduction. Rappelez-vous comment nous venons de mentionner que l'index 0
sera ignoré? Cela signifie que la première passe, la valeur nous donnera 5
et index
sera 1
. La deuxième passe nous donnera une valeur
de 1
et l'index
2.
Exécutez ce code et vérifiez la console, et même jouez avec les journaux de la console et les valeurs, ajoutez plus de billes au tableau
. Une fois que vous le verrez en mouvement, cela deviendra plus clair. Voici un violon à essayer:
https://jsfiddle.net/jx7aw3rz/4/ .
Pour aller plus loin: Gemcutting 101
Ok ouais, réduire
est vraiment sympa pour exécuter un ensemble fixe de valeurs via une simple fonction mathématique, mais je suppose que vous voulez apprendre à l'utiliser avec des choses plus intéressantes comme le traitement d'un lot de données, ou même le filtrage. [19659003] Imaginons que nous construisions un jeu, une sorte de RPG (Role Playing Game), et nous voulons créer une fonction reduction
qui prend toutes les gemmes de nos joueurs et les coupe.
Avant quoi que ce soit, nous allons faire une petite configuration avec quelques variables et une fonction.
const gems = [
{
type : 'Ruby'
coupe : false
valeur : 100
requiredSkill : 1
}
{
type : 'Saphir'
coupe : false
valeur : 200
requiredSkill : 2
}
{
type : 'Opal'
coupe : false
valeur : 250
requiredSkill : 8
}
{
type : 'Diamond'
coupe : false
valeur : 300
requiredSkill : 5
}
]
const gemcuttingSkill = 4
const cutGem = gem => {
if ( gem . requiredSkill > gemcuttingSkill ) return
gem . valeur = gemme . valeur * 3
gem . cut = true
}
Notre tableau gemmes
sera un tableau d'objets, et chacun sera un objet gemme. [19659003] Ensuite, gemcuttingSkill
sera une valeur numérique qui indiquera la compétence dont l'utilisateur a besoin pour couper une gemme – si la gemme a une très haute requiredSkill
l'utilisateur ne le fera pas pouvoir le couper.
Enfin, nous avons une fonction appelée cutGem
. Il prend un seul paramètre, un gemme
et il tente de le couper. Cependant, tout d’abord, il vérifie la compétence de l’utilisateur. Notez également que la valeur
d’une gemme augmente de 3 quand elle est coupée!
Écrivons la fonction de réduction qui utilisera la fonction cutGem
sur toutes nos gemmes. Nous allons cependant faire une petite exception! Nous ne couperons aucun Diamants
– ils sont trop rares pour être coupés. Celles-ci vont à la maison de ventes.
const cutGems = gemmes . reduction ( ( acc gem index ) => {
console . log ( 'Processing gem:' gem )
console . log ( 'With index' index )
if ( gem . ] type === 'Diamond' ) {
return acc
}
cutGem ( gem )
if (! gem . cut ) [19659016] {
retour acc
}
acc . push ( gem )
return acc
} [] )
console . log ( cutGems )
Nous appelons .reduce
sur notre tableau de gemmes, et nous nommons notre accumulateur
paramètre selon
. C'est une convention courante que vous pouvez trouver dans certains articles et ressources.
Le deuxième paramètre que la fonction reçoit est le gem
car nous parcourons le tableau en boucle.
Maintenant, je veux que vous pour jeter un coup d'œil à la fin du bloc fonction, juste après return acc
– ne vous inquiétez pas, nous reviendrons à la fonction dans une minute. Voyez-vous ce tableau vide que nous transmettons comme deuxième paramètre à l'appel reduction
? C'est la valeur par défaut
ou commençant
pour l'accumulateur
.
Plus tôt, quand nous regardions l'exemple avec les billes, je vous ai dit que le premier élément avait déjà été ajouté à l'accumulateur pour nous gratuitement, mais que se passe-t-il si nous voulons fournir une valeur initiale pour notre accumulateur et la manipuler dans la fonction réduire
?
La solution est de passer dans un deuxième argument facultatif de array.reduce
qui sera la valeur par défaut. Ainsi, la première fois que la fonction que nous fournissons pour gems.reduce
est appelée, acc
aura une valeur de []
et le gem
] que nous obtenons sera celui à index 0
!
Ok, revenons au contenu de la fonction. Nous allons d'abord enregistrer quelques éléments afin de voir dans la sortie de la console comment la réduction fonctionne.
Ensuite, nous ajoutons une instruction if
– nous vérifierons si le gem
est du type Diamond
. Si tel est le cas, nous retournerons le acc
lui-même sans le modifier, car nous ne voulons pas y ajouter cette gemme. Gardez à l'esprit que vous devez toujours
renvoyer le acc
dans la fonction réduire
même si vous ne l'avez pas modifié. cutGem
avec l'actuel gem
comme paramètre. Notre fonction exécutera et coupera la gemme si le joueur a le niveau de compétence requis. Ensuite, nous vérifierons si la gemme a été réellement coupée dans la prochaine déclaration if
. Si ce n'est pas le cas, nous allons renvoyer le acc
dans ce cas également.
Enfin, nous poussons la gemme coupée
dans le acc
Tout ce processus sera exécuté pour notre sac de gemmes, un par un, et nous retournerons dans notre const cutGem
un tableau des gemmes qui ont été coupées. [19659003] Allons plus loin et utilisons array.reduce
une fois de plus pour calculer la valeur des gemmes coupées, s'il y en a.
const gemValue = gemmes . réduire ( ( acc gem ) => {
return acc + gemme . valeur
} 0 )
console . log ( `Les gemmes taillées ont une valeur de $ { gemValue } gold` ) [19659063] Une fois de plus, nous avons un appel réduire
sur notre tableau gemmes
- mais faites très attention à la valeur par défaut. Cette fois, nous le définissons sur 0.
Si nous sautions ce petit détail et omettions la valeur par défaut pour le acc
alors notre fonction de réduction recevrait la gemme entière
comme la valeur du acc
ce qui n'est pas ce que nous voulons. Nous voulons traiter uniquement des nombres.
A l'intérieur de la fonction, nous parcourons chaque coupe gemme
et nous renvoyons la valeur actuelle du acc
plus la valeur de la gemme actuelle . Ainsi, chaque fois que nous parcourons la boucle, la gem.value
sera ajoutée à la valeur accumulée, et ainsi de suite.
Voici un violon pour que vous puissiez exécuter et tester ce code:
https : //jsfiddle.net/m7agkudx/ .
Conclusion
Array.reduce
est l'une de ces fonctions dont le nom n'est parfois pas très descriptif de ce qu'il fait . La flexibilité que nous obtenons pour traiter les éléments de tableau avec cette fonction est fantastique, mais a un coût d'une courbe d'apprentissage plus élevée.
J'espère qu'avec ces quelques exemples stupides, vous serez en mesure de plonger directement et de commencer à écrire le vôtre ] Réduisez les
fonctions!
Comme toujours, merci d'avoir lu et partagez avec moi vos réflexions sur Twitter à: @marinamosti .
PS Tous saluent l'avocat magique!
P.P.S. 


Source link