Jak používat Reduce to Total Array of Objects v JavaScriptu

Jak používat metodu JavaScript Array.reduce ke smyčce přes pole položek představujících košík a vygenerovat objekt s mezisoučtem, součtem daně a součtem (mezisoučet + daň).

Začínáme

Protože kód, který píšeme pro tento tutoriál, je „samostatný“ (to znamená, že není součástí větší aplikace nebo projektu), vytvoříme projekt Node.js od začátku. Pokud ještě nemáte na svém počítači nainstalovaný Node.js, přečtěte si nejprve tento návod a poté se vraťte sem.

Jakmile budete mít v počítači nainstalovaný soubor Node.js, ze složky projektů v počítači (např. ~/projects ), vytvořte novou složku pro naši práci:

Terminál

mkdir reduce

Dále cd do tohoto adresáře a vytvořte index.js soubor (zde budeme psát náš kód pro tutoriál):

Terminál

cd reduce && touch index.js

Díky tomu jsme připraveni začít.

Vytvoření pole položek

První věc, kterou musíme udělat, je vytvořit pole položek, které budou reprezentovat náš košík. Každá položka v košíku bude mít čtyři vlastnosti:

  1. id – Jedinečné ID položky jako celé číslo.
  2. name – Název položky jako řetězec.
  3. quantity – Množství této položky nakupované jako celé číslo.
  4. amount – Částka za položku jako plovoucí (desítkové) číslo.

Pojďme přidat příklad pole do našeho souboru. Neváhejte a změňte to, jak uznáte za vhodné (jen se ujistěte, že používáte stejné názvy klíčů pro každý objekt a správné datové typy pro hodnoty).

/index.js

const items = [
  { id: 1, name: 'Coffee Maker', quantity: 3, amount: 29.22 },
  { id: 2, name: 'Toaster Oven', quantity: 1, amount: 129.19 },
  { id: 3, name: 'Chef\'s Knife', quantity: 10, amount: 39.38 },
  { id: 4, name: 'Deep Fryer', quantity: 4, amount: 209.61 },
  { id: 5, name: 'Espresso Machine', quantity: 2, amount: 89.49 },
];

Dále, než přejdeme k naší funkci snížení, přidejte další proměnnou taxRate do našeho souboru, který bude obsahovat procento daně, které chceme vypočítat pro každou položku:

/index.js

const items = [
  { id: 1, name: 'Coffee Maker', quantity: 3, amount: 29.22 },
  { id: 2, name: 'Toaster Oven', quantity: 1, amount: 129.19 },
  { id: 3, name: 'Chef\'s Knife', quantity: 10, amount: 39.38 },
  { id: 4, name: 'Deep Fryer', quantity: 4, amount: 209.61 },
  { id: 5, name: 'Espresso Machine', quantity: 2, amount: 89.49 },
];

const taxRate = 0.0625; // 6.25%

Zde, jak z komentáře vyplývá, naše daňová sazba bude 6,25 %. To je vyjádřeno jako float 0.0625 .

Pomocí Array.reduce vygenerujte objekt

Nyní, když máme nějaké položky, se kterými můžeme pracovat, jsme připraveni vložit .reduce() pracovat na našem poli. Nejdříve vytvořme svůj hovor a promluvme si o konečném cíli.

/index.js

const items = [
  ...
];

const taxRate = 0.0625; // 6.25%

const cart = items.reduce((acc = {}, item = {}) => {
  // We'll handle our calculations here...

  return acc;
}, {
  subtotal: 0,
  tax: 0,
  total: 0
});

console.log(cart);

Důležitá věc, kterou je třeba pochopit o .reduce() je, že je to standardní metoda pole v JavaScriptu, stejně jako .forEach() nebo .map() . Co je jedinečného na .reduce() spočívá v tom, že je navržen tak, aby smyčkoval pole stejně jako jeho sourozenecké metody, ale místo toho, aby pouze smyčkoval pole (jako .forEach() ) nebo opakování přes pole a vrácení upraveného pole (jako .map() ), je navržen tak, aby "redukoval pole na něco jiného."

Při vaření se výraz „redukovat“ používá k uvaření něčeho do jiné formy (např. rozpuštění másla spolu s česnekem a vytvoření jednoduché omáčky).

Zde chceme „zmenšit“ naše pole položek na objekt, který vypadá takto:

{
  subtotal: 0,
  tax: 0,
  total: 0,
}

Myšlenka je taková, že pro každou iteraci nebo "smyčku" přes naše pole přidáme k hodnotám tohoto objektu (subtotal , tax a total ), vracející tento objekt, jakmile dosáhneme konce pole.

/index.js

const items = [
  ...
];

const taxRate = 0.0625; // 6.25%

const cart = items.reduce((acc = {}, item = {}) => {
  // We'll handle our calculations here...

  return acc;
}, {
  subtotal: 0,
  tax: 0,
  total: 0
});

console.log(cart);

Chcete-li zvládnout doplňkovou část, do .reduce() předáme funkci, která je volána pro každou iteraci nebo "smyčku" přes naše pole položek. Této funkci jsou předány dva argumenty:acc (zkratka pro akumulátor) a item aktuální položka je opakována.

Zde acc je objekt, který nakonec vrátíme z našeho volání na .reduce() (v tomto tutoriálu je celkový počet našich košíků). Pokud se podíváme na naše volání na .reduce() zde si všimneme, že funkce, kterou jsme právě popsali, je prvním argumentem, který předáme, zatímco počáteční hodnota pro akumulátor (acc ) je předán jako druhá hodnota. Ačkoli jako výchozí hodnotu používáme objekt, technicky to může být jakákoli Hodnota JavaScriptu (např. řetězec, celé číslo nebo jiné pole).

Zde můžeme očekávat, že když naše .reduce() běží poprvé (což znamená, že se iteruje přes první položku v poli nebo v našem příkladu položku „Kávovar“ v košíku), hodnota acc argument předaný funkci předaný .reduce() je:{ subtotal: 0, tax: 0, total: 0 } .

Naším cílem je získat acc a upravte jej pro každou iteraci nebo "smyčku" přes naše items pole pomocí aktuální hodnoty item k tomu.

/index.js

const items = [
  ...
];

const taxRate = 0.0625; // 6.25%

const cart = items.reduce((acc = {}, item = {}) => {
  const itemTotal = parseFloat((item.amount * item.quantity).toFixed(2));
  const itemTotalTax = parseFloat((itemTotal * taxRate).toFixed(2));

  // We'll modify acc here...

  return acc;
}, {
  subtotal: 0,
  tax: 0,
  total: 0
});

console.log(cart);

Než upravíme naše acc (akumulátor), musíme pro naši položku provést nějaké výpočty a formátování. Naším cílem pro každou položku je vygenerovat dva součty:součet pro samotnou položku (jeho amount vynásobený jeho quantity ) a výši daně pro danou položku.

Abychom to udělali, přesuneme se zevnitř ven, nejprve vynásobíme item.amount hodnotu s item.quantity . Protože výsledkem by mohlo být dlouhé desetinné číslo (např. 191.07180001 ) zabalíme tento výpočet do závorek a pak zavoláme .toFixed(2) metoda. Takže je to jasné, děláme toto:

(item.amount * item.quantity) // Produces a number which is captured by the parentheses.
(123.2910181).toFixed(2) // Converts the resulting number to a two place decimal number, formatted as a string.

.toFixed(2) metoda zde říká "vezměte jakékoli číslo, které bylo vyrobeno z výpočtu, a převeďte jej na dvě desetinná místa." Pokud je třetí desetinná číslice větší nebo rovna 5, bude zaokrouhlena nahoru (např. 123.0157181 bude zaokrouhleno na 123.02 ), zatímco hodnota menší než 5 bude zaokrouhlena dolů (např. 123.014571811 bude zaokrouhleno na 123.01 ) podle .toFixed() .

Je tu drobný problém, který jste pravděpodobně uhodli:toto nám dává naše číslo jako řetězec, nikoli jako plovoucí (dissentery JavaScriptu 1, vývojáři JavaScriptu 0), což ztěžuje naši schopnost provádět další výpočty.

Abychom to obešli, zabalíme naše (item.amount * item.quantity).toFixed(2) výpočet s voláním na parseFloat() který, jak název napovídá, převádí jakoukoli hodnotu, kterou mu předáme, na plovoucí číslo JavaScriptu. Pokud tedy předáme něco jako "123.02" , dostaneme zpět skutečné plovoucí číslo 123.02 .

Pro itemTotalTax , používáme stejný přesný přístup, ale pro toto číslo vynásobíme itemTotal právě jsme počítali s taxRate proměnná, kterou jsme definovali dříve.

/index.js

const items = [
  { id: 1, name: 'Coffee Maker', quantity: 3, amount: 29.22 },
  { id: 2, name: 'Toaster Oven', quantity: 1, amount: 129.19 },
  { id: 3, name: 'Chef\'s Knife', quantity: 10, amount: 39.38 },
  { id: 4, name: 'Deep Fryer', quantity: 4, amount: 209.61 },
  { id: 5, name: 'Espresso Machine', quantity: 2, amount: 89.49 },
];

const taxRate = 0.0625; // 6.25%

const cart = items.reduce((acc = {}, item = {}) => {
  const itemTotal = parseFloat((item.amount * item.quantity).toFixed(2));
  const itemTotalTax = parseFloat((itemTotal * taxRate).toFixed(2));

  acc.subtotal = parseFloat((acc.subtotal + itemTotal).toFixed(2));
  acc.tax = parseFloat((acc.tax + itemTotalTax).toFixed(2));
  acc.total = parseFloat((acc.total + itemTotal + itemTotalTax).toFixed(2));

  return acc;
}, {
  subtotal: 0,
  tax: 0,
  total: 0
});

console.log(cart);

Nyní k té zábavnější části. S naším itemTotal a itemTotalTax , jsme připraveni upravit náš acc (akumulátor). Pamatujte:měníme acc pro každou iteraci nebo "smyčku" přes naše items pole .

K tomu stačí vzít acc argument předaný naší funkci a upravit jej. Pamatujte:technicky vzato acc může obsahovat libovolnou hodnotu, víme však, že obsahuje objekt JavaScript, protože jsme předali jako druhý argument .reduce() .

Z tohoto důvodu chceme na daném objektu upravit jednotlivé vlastnosti. Zde upravujeme acc.subtotal , acc.tax a acc.total . U každého si všimněte, že nastavujeme hodnotu rovnou aktuální hodnota tohoto majetku plus odpovídající celková částka, kterou jsme právě vypočítali (buď celková částka nebo celková daň položky).

Všimněte si, že abychom zachovali naše čísla pevně na dvě desetinná místa, používáme .toFixed(2) v kombinaci s parseFloat() trik pro každý ze součtů, které jsme na objektu nastavili.

I když vidíme pouze konečný výsledek (ten bude uložen v cart proměnnou jsme přiřadili naše volání items.reduce() to), pokud odhlásíme každou iteraci naší smyčky, očekávali bychom, že uvidíme něco takového:

{ subtotal: 0, tax: 0, total: 0 } // Initial value for acc we set as a default.
{ subtotal: 87.66, tax: 5.48, total: 93.14 }
{ subtotal: 216.85, tax: 13.55, total: 230.4 }
{ subtotal: 610.65, tax: 38.16, total: 648.81 }
{ subtotal: 1449.09, tax: 90.56, total: 1539.65 }
{ subtotal: 1628.07, tax: 101.75, total: 1729.82 }

Důležitá část :všimněte si, že úplně dole ve funkci přejdeme na .reduce() ujistíme se, že return acc hodnota po upravili jsme to. Toto je povinné . Takto vypadá .reduce() aktualizuje hodnotu acc poté, co jsme jej upravili.

A je to! Nyní pro každou iteraci naší smyčky upravíme acc uložením konečného výsledku do proměnné cart . Na konec našeho souboru přidejte console.log(cart) takže můžeme vidět výstup, když spustíme náš kód.

Chcete-li jej spustit, v terminálu z kořenové složky našeho projektu, pokud spustíme node index.js měli bychom vidět něco jako toto odhlášení:

{ subtotal: 1628.07, tax: 101.75, total: 1729.82 }

Zabalení

V tomto tutoriálu jsme se naučili používat Array.reduce() metoda v JavaScriptu pro převod pole objektů na jeden objekt. Abychom demonstrovali použití, vytvořili jsme fiktivní košík items a použít snížit k výpočtu součtu pro každou položku spolu s její sazbou daně.