JavaScript réduit les erreurs de lancement pour plus de deux éléments

Sep 22 2020

J'ai ce tableau:

const arr = [
  { someProp: [{ amount: 10 }]},
  { someProp: [{ amount: 12 }]},
];

puis cela réduit fn:

const sum = arr.reduce((prev, curr) => prev.someProp[0].amount + curr.someProp[0].amount);

Cela fonctionne s'il y a deux éléments dans le tableau mais avec trois, il en lance:

Impossible de lire la propriété "0" sur undefined "

Réponses

2 Ifaruki Sep 22 2020 at 13:06

En fait, il vous suffit de renvoyer l'accumulateur + la nouvelle valeur.

Vous voulez commencer par 0je suppose que vous devez donc ajouter 0comme deuxième paramètre

const arr =
    [
      { someProp: [{ amount: 10 }]},
      { someProp: [{ amount: 12 }]},
      { someProp: [{ amount: 12 }]},
    ];
    
const sum = arr.reduce((acc, item) => item.someProp[0].amount + acc, 0);

console.log(sum);

Si vous le voulez plus épicé ici avec déstructuration

const arr =
    [
      { someProp: [{ amount: 10 }]},
      { someProp: [{ amount: 12 }]},
      { someProp: [{ amount: 12 }]},
    ];
    
const sum = arr.reduce((acc, { someProp: [{ amount }] }) => amount + acc, 0);

console.log(sum);

2 CristianTraìna Sep 22 2020 at 13:06

Suite à la réponse @Pointy, voici comment vous pouvez le faire fonctionner avec n'importe quel nombre d'éléments:

const sum = arr.reduce((prev, curr) => prev + curr.someProp[0].amount, 0);

prevest toujours l'élément précédemment renvoyé, vous pouvez donc l'utiliser en toute sécurité comme un nombre (et comme vous ne faites que l'additionner, vous pouvez l'utiliser 0 par défaut, de sorte que reducela valeur de prevsera 0 pour la première fois )

2 Pointy Sep 22 2020 at 13:00

Vous renvoyez un numéro. La valeur de prevest toujours la valeur de retour précédente du rappel, et non l'élément précédent. Ainsi, à la troisième itération, vous essayez d'utiliser ce nombre comme s'il s'agissait d'une référence d'objet.

Ajoutez un deuxième paramètre (0) à l' .reduce()appel et modifiez la fonction à traiter prevcomme le total cumulé (un simple nombre):

const sum = arr.reduce((prev, curr) => prev + curr.someProp[0].amount, 0);

Il fonctionne tel quel lorsqu'il y a deux éléments car sans ce second paramètre, la première itération verra l'élément 0 comme prevet l'élément 1 comme curr. Ce comportement fonctionne bien lorsque vous avez un tableau de nombres et que vous souhaitez simplement effectuer un calcul entre eux, mais dans ce cas, vous avez besoin de cette valeur initiale explicitement comme deuxième argument.

PeterDarmis Sep 22 2020 at 13:39

Ceci est une solution alternative ... Utilisation Array.filter().

const arr = [{
    someProp: [{
      amount: 10
    }]
  },
  {
    someProp: [{
      amount: 12
    }]
  },
  {
    someProp: [{
      amount: -231
    }]
  },
  {
    someProp: [{
      amount: 21265
    }]
  },
  {
    someProp: [{
      amount: 1239
    }]
  },
  {
    someProp: [{
      amount: -6
    }]
  },
];
const sum = arr.filter((val, index) => {
  if (index > 0) {
    arr[index].someProp[0].amount = parseInt(val.someProp[0].amount) + parseInt(arr[index - 1].someProp[0].amount);
  }
  return index == arr.length - 1;
})[0].someProp[0].amount;

console.log(sum);