Vodič za metodu smanjenja u Javascriptu

JavaScript-ova metoda redukcije jedan je od temelja funkcionalnog programiranja.Istražimo kako to funkcionira, kada biste ga trebali koristiti i neke od sjajnih stvari koje on može učiniti.

Osnovno smanjenje

Koristite ga kada : Imate niz iznosa i želite ih sve zbrojiti.

const euros = [29.76, 41.85, 46.5]; const sum = euros.reduce((total, amount) => total + amount); sum // 118.11

Kako ga koristiti:

  • U ovom primjeru, Reduce prihvaća dva parametra, ukupni i trenutni iznos.
  • Metoda reducira ciklus kroz svaki broj u nizu slično kao što bi to učinila for-petlja.
  • Kad petlja započne, ukupna vrijednost je broj krajnje lijevo (29,76), a trenutni iznos je onaj pored nje (41,85).
  • U ovom konkretnom primjeru želimo zbrojiti trenutni iznos.
  • Izračun se ponavlja za svaki iznos u polju, ali svaki put kada se trenutna vrijednost promijeni u sljedeći broj u polju, pomičući se udesno.
  • Kada u nizu više nema brojeva, metoda vraća ukupnu vrijednost.

ES5 verzija metode smanjenja u JavaScript-u

Ako nikada prije niste koristili sintaksu ES6, ne dopustite da vas gornji primjer zastraši. To je potpuno isto kao i pisanje:

var euros = [29.76, 41.85, 46.5]; var sum = euros.reduce( function(total, amount){ return total + amount }); sum // 118.11

Riječ koristimo constumjesto riječi vari zamjenjujemo functionje „masnom strelicom“ ( =>) nakon parametara, a riječ „povratak“ izostavljamo.

Za ostale primjere upotrijebit ću sintaksu ES6, jer je sažetija i ostavlja manje mjesta za pogreške.

Pronalaženje prosjeka metodom smanjenja u JavaScript-u

Umjesto bilježenja zbroja, zbroj možete podijeliti s duljinom polja prije nego što vratite konačnu vrijednost.

To se postiže iskorištavanjem ostalih argumenata u metodi redukcije. Prvi od tih argumenata je indeks . Slično kao for-loop, indeks se odnosi na broj puta koji je reduktor prešao preko niza. Posljednji argument je sam niz .

const euros = [29.76, 41.85, 46.5]; const average = euros.reduce((total, amount, index, array) => { total += amount; if( index === array.length-1) { return total/array.length; }else { return total; } }); average // 39.37

Karta i filtriraj kao smanjenja

Ako možete koristiti funkciju smanjivanja da ispljunete prosjek, tada je možete koristiti na bilo koji način.

Na primjer, mogli biste udvostručiti ukupno, ili pola svaki broj prije nego ih dodate zajedno ili upotrijebiti ako izjava unutar reduktor samo dodati brojeve koji su veći od 10. Moj point je da je smanjenje Metoda Da JavaScript daje mini CodePen gdje možete napisati bilo koju logiku koju želite. To će ponoviti logiku za svaki iznos u polju, a zatim se vratiti jednu vrijednost.

Stvar je u tome što ne morate uvijek vratiti jednu vrijednost. Niz možete smanjiti u novi niz.

Na primjer, omogućuje smanjenje niza iznosa u drugi niz gdje se svaki iznos udvostručuje. Da bismo to učinili, početnu vrijednost za naš akumulator moramo postaviti na prazan niz.

Početna vrijednost je vrijednost ukupnog parametra kada započinje smanjenje. Početna vrijednost postavljate dodavanjem zareza nakon kojeg slijedi početna vrijednost unutar zagrada, ali nakon kovrčavih zagrada ( podebljano u donjem primjeru ).

const average = euros.reduce((total, amount, index, array) => { total += amount return total/array.length }, 0);

U prethodnim primjerima početna vrijednost bila je nula pa sam je izostavio. Izostavljanjem početne vrijednosti, ukupni će zadani iznos biti prvi u nizu.

Postavljanjem početne vrijednosti na prazan niz tada možemo svaki iznos ugurati u zbroj . Ako želimo smanjiti niz vrijednosti u drugi niz u kojem je svaka vrijednost udvostručena, moramo potisnuti iznos * 2. Zatim vraćamo zbroj kada više nema iznosa za potiskivanje.

const euros = [29.76, 41.85, 46.5]; const doubled = euros.reduce((total, amount) => { total.push(amount * 2); return total; }, []); doubled // [59.52, 83.7, 93]

Stvorili smo novi niz u kojem se svaki iznos udvostručuje. Također bismo mogli filtrirati brojeve koje ne želimo udvostručiti dodavanjem izraza if unutar našeg reduktora.

const euro = [29.76, 41.85, 46.5]; const above30 = euro.reduce((total, amount) => { if (amount > 30) { total.push(amount); } return total; }, []); above30 // [ 41.85, 46.5 ]

Te su operacije metode mape i filtra prepisane kao metoda smanjenja.

Za ove bi primjere imalo više smisla koristiti kartu ili filtar jer su jednostavniji za upotrebu. Prednost korištenja smanjenja dolazi u obzir kada želite mapirati i filtrirati zajedno i ako imate mnogo podataka za pregledavanje.

Ako zajedno povežete mapu i filtrirate, posao radite dva puta. Filtrirate svaku pojedinu vrijednost, a zatim mapirate preostale vrijednosti. Smanjenjem možete filtrirati, a zatim mapirati u jednom prolazu.

Koristite mapu i filtar, ali kad započnete ulančavati puno metoda, sada znate da je brže smanjivanje podataka.

Stvaranje Tally metode redukcije u JavaScript-u

Koristite ga kada : imate zbirku predmeta i želite znati koliko se svake stavke nalazi u zbirci.

const fruitBasket = ['banana', 'cherry', 'orange', 'apple', 'cherry', 'orange', 'apple', 'banana', 'cherry', 'orange', 'fig' ]; const count = fruitBasket.reduce( (tally, fruit) =>  , {}) count // { banana: 2, cherry: 3, orange: 3, apple: 2, fig: 1 }

Da bismo zbrajali stavke u polju, naša početna vrijednost mora biti prazan objekt, a ne prazan niz kao što je bio u prošlom primjeru.

Budući da ćemo vratiti objekt, sada možemo ukupno pohraniti parove ključ / vrijednost.

fruitBasket.reduce( (tally, fruit) => { tally[fruit] = 1; return tally; }, {})

Pri prvom prolazu želimo da ime prvog ključa bude naša trenutna vrijednost i želimo mu dati vrijednost 1.

To nam daje objekt sa svim plodovima kao ključevima, svaki s vrijednošću 1. Želimo da se količina svakog voća poveća ako se ponovi.

Da bismo to učinili, u našoj drugoj petlji provjeravamo sadrži li naš zbroj ključ s trenutnim plodom reduktora. Ako ne, onda ga mi stvaramo. Ako se dogodi, povećavamo iznos za jedan.

fruitBasket.reduce((tally, fruit) => { if (!tally[fruit]) { tally[fruit] = 1; } else { tally[fruit] = tally[fruit] + 1; } return tally; }, {});

Potpuno istu logiku prepisao sam na sažetiji način gore.

Izravnavanje niza nizova metodom redukcije u JavaScript-u

Smanjivanje možemo koristiti za izravnavanje ugniježđenih količina u jedan niz.

Početnu vrijednost postavljamo na prazan niz, a zatim trenutnu vrijednost spajamo u ukupnu.

const data = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; const flat = data.reduce((total, amount) => { return total.concat(amount); }, []); flat // [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]

Informacije su češće ugniježđene na složenije načine. Na primjer, recimo da samo želimo sve boje u donjoj varijabli podataka.

const data = [ {a: 'happy', b: 'robin', c: ['blue','green']}, {a: 'tired', b: 'panther', c: ['green','black','orange','blue']}, {a: 'sad', b: 'goldfish', c: ['green','red']} ];

Kročit ćemo kroz svaki predmet i izvući boje. To radimo ukazujući iznos.c za svaki objekt u nizu. Zatim koristimo forEach petlju za guranje svake vrijednosti u ugniježđenom nizu u ukupno.

const colors = data.reduce((total, amount) => { amount.c.forEach( color => { total.push(color); }) return total; }, []) colors //['blue','green','green','black','orange','blue','green','red']

Ako nam treba samo jedinstveni broj, možemo provjeriti postoji li taj broj ukupno prije nego što ga pritisnemo.

const uniqueColors = data.reduce((total, amount) => { amount.c.forEach( color => { if (total.indexOf(color) === -1){ total.push(color); } }); return total; }, []); uniqueColors // [ 'blue', 'red', 'green', 'black', 'orange']

Cjevovod sa redukcijom

An interesting aspect of the reduce method in JavaScript is that you can reduce over functions as well as numbers and strings.

Let’s say we have a collection of simple mathematical functions. these functions allow us to increment, decrement, double and halve an amount.

function increment(input) { return input + 1;} function decrement(input) { return input — 1; } function double(input) { return input * 2; } function halve(input) { return input / 2; }

For whatever reason, we need to increment, then double, then decrement an amount.

You could write a function that takes an input, and returns (input + 1) * 2 -1. The problem is that we know we are going to need to increment the amount three times, then double it, then decrement it, and then halve it at some point in the future. We don’t want to have to rewrite our function every time so we going to use reduce to create a pipeline.

A pipeline is a term used for a list of functions that transform some initial value into a final value. Our pipeline will consist of our three functions in the order that we want to use them.

let pipeline = [increment, double, decrement];

Instead of reducing an array of values we reduce over our pipeline of functions. This works because we set the initial value as the amount we want to transform.

const result = pipeline.reduce(function(total, func) { return func(total); }, 1); result // 3

Because the pipeline is an array, it can be easily modified. If we want to decrement something three times, then double it, decrement it , and halve it then we just alter the pipeline.

var pipeline = [ increment, increment, increment, double, decrement, halve ];

The reduce function stays exactly the same.

Silly Mistakes to avoid

If you don’t pass in an initial value, reduce will assume the first item in your array is your initial value. This worked fine in the first few examples because we were adding up a list of numbers.

If you’re trying to tally up fruit, and you leave out the initial value then things get weird. Not entering an initial value is an easy mistake to make and one of the first things you should check when debugging.

Another common mistake is to forget to return the total. You must return something for the reduce function to work. Always double check and make sure that you’re actually returning the value you want.

Tools, Tips & References

  • Everything in this post came from a fantastic video series on egghead called Introducing Reduce. I give Mykola Bilokonsky full credit and I am grateful to him for everything I now know about using the Reduce Method In JavaScript​. I have tried to rewrite much of what he explains in my own words as an exercise to better understand each concept. Also, it’s easier for me to reference an article, as opposed to a video, when I need to remember how to do something.
  • The MDN Reduce documentation labels what I called a total the accumulator. It is important to know this because most people will refer to it as an accumulator if you read about it online. Some people call it prev as in previous value. It all refers to the same thing. I found it easier to think of a total when I was learning reduce.
  • If you would like to practice using reduce I recommend signing up to freeCodeCamp and completing as many of the intermediate algorithms as you can using reduce.
  • If the ‘const’ variables in the example snippets are new to you I wrote another article about ES6 variables and why you might want to use them.
  • I also wrote an article called The Trouble With Loops that explain how to use map() and filter() if the are new to you.

Thanks for reading! If you’d like to be notified when I write a new article please enter your email here.

And if you liked the article, please share it on social media so others can find it.