Fermer

avril 23, 2021

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

 Britney Spears semble confuse

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