Sådan forenkles din codebase med map (), reducerer () og filter () i JavaScript

Når du læser om Array.reduce, og hvor sejt det er, er det første og undertiden det eneste eksempel, du finder, summen af ​​tal. Dette er ikke vores definition af 'nyttigt'. ?

Desuden har jeg aldrig set det i en rigtig codebase. Men hvad jeg har set meget, er 7-8 linier for-loop-udsagn til løsning af en regelmæssig opgave, hvor Array.reduce kunne gøre det på en linje.

For nylig omskrev jeg et par moduler ved hjælp af disse fantastiske funktioner. Det overraskede mig, hvor forenklet kodebasen blev. Så nedenfor er en liste over godbidder.

Hvis du har et godt eksempel på at bruge et kort eller en formindskelsesmetode - send det i kommentarfeltet. ?

Lad os komme igang!

1. Fjern dubletter fra en række tal / strenge

Nå, dette er den eneste, der ikke handler om kort / formindsk / filter , men det er så kompakt, at det var svært ikke at placere det på listen. Plus, vi bruger det også i et par eksempler.

const values = [3, 1, 3, 5, 2, 4, 4, 4]; const uniqueValues = [...new Set(values)]; // uniqueValues is [3, 1, 5, 2, 4]

2. En simpel søgning (store og små bogstaver)

Metoden filter () opretter et nyt array med alle elementer, der består testen implementeret af den leverede funktion.

const users = [ { id: 11, name: 'Adam', age: 23, group: 'editor' }, { id: 47, name: 'John', age: 28, group: 'admin' }, { id: 85, name: 'William', age: 34, group: 'editor' }, { id: 97, name: 'Oliver', age: 28, group: 'admin' } ]; let res = users.filter(it => it.name.includes('oli')); // res is []

3. En simpel søgning (store og små bogstaver)

let res = users.filter(it => new RegExp('oli', "i").test(it.name)); // res is [ { id: 97, name: 'Oliver', age: 28, group: 'admin' } ]

4. Kontroller, om nogen af ​​brugerne har administratorrettigheder

Metoden some () tester, om mindst et element i arrayet består testen, der er implementeret af den leverede funktion.

const hasAdmin = users.some(user => user.group === 'admin'); // hasAdmin is true

5. Fladning af en række arrays

Resultatet af den første iteration er lig med: [… [],… [1, 2, 3]] betyder, at den omdannes til [1, 2, 3] - denne værdi giver vi som en 'acc' på den anden iteration og snart.

const nested = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; let flat = nested.reduce((acc, it) => [...acc, ...it], []); // flat is [1, 2, 3, 4, 5, 6, 7, 8, 9]

Vi kan forbedre denne kode lidt ved at udelade et tomt array []som det andet argument for reducere (). Derefter vil den første værdi af den indlejrede blive brugt som den indledende acc- værdi. Tak til Vladimir Efanov.

let flat = nested.reduce((acc, it) => [...acc, ...it]); // flat is [1, 2, 3, 4, 5, 6, 7, 8, 9]

Bemærk, at det ikke er en god ide at bruge spredeoperatøren i en reducering . Dette eksempel er et tilfælde, når måling af ydeevne giver mening i din brugssag. ☝️

Takket være Paweł Wolak er her en kortere vej uden Array. Reducer:

let flat = [].concat.apply([], nested);

Også Array.flat kommer, men det er stadig en eksperimentel funktion.

6. Opret et objekt, der indeholder frekvensen for den angivne nøgle

Lad os gruppere og tælle egenskaben 'alder' for hvert element i matrixen:

const users = [ { id: 11, name: 'Adam', age: 23, group: 'editor' }, { id: 47, name: 'John', age: 28, group: 'admin' }, { id: 85, name: 'William', age: 34, group: 'editor' }, { id: 97, name: 'Oliver', age: 28, group: 'admin' } ]; const groupByAge = users.reduce((acc, it) => , {}); // groupByAge is {23: 1, 28: 2, 34: 1}

Tak til sai krishna for at foreslå denne!

7. Indeksering af en række objekter (opslagstabel)

I stedet for at behandle hele arrayet til at finde en bruger efter id, kan vi konstruere et objekt, hvor brugerens id repræsenterer en nøgle (med konstant søgetid).

const uTable = users.reduce((acc, it) => (acc[it.id] = it, acc), {}) // uTable equals: { 11: { id: 11, name: 'Adam', age: 23, group: 'editor' }, 47: { id: 47, name: 'John', age: 28, group: 'admin' }, 85: { id: 85, name: 'William', age: 34, group: 'editor' }, 97: { id: 97, name: 'Oliver', age: 28, group: 'admin' } }

Det er nyttigt, når du skal have adgang til dine data ved id som uTable[85].namemeget.

8. Uddrag de unikke værdier for den givne nøgle for hvert element i arrayet

Lad os oprette en liste over eksisterende brugergrupper. Den kortet () metode skaber en ny array med resultaterne af at kalde en forudsat funktion på hvert enkelt element i den kaldende array.

const listOfUserGroups = [...new Set(users.map(it => it.group))]; // listOfUserGroups is ['editor', 'admin'];

9. Gendannelse af genstandsnøgleværdikort

const cities = { Lyon: 'France', Berlin: 'Germany', Paris: 'France' }; let countries = Object.keys(cities).reduce( (acc, k) => (acc[cities[k]] = [...(acc[cities[k]] || []), k], acc) , {}); // countries is { France: ["Lyon", "Paris"], Germany: ["Berlin"] }

Denne one-liner ser ret vanskelig ud. Vi bruger kommaoperatoren her, og det betyder, at vi returnerer den sidste værdi i parentes - acc. Lad os omskrive dette eksempel på en mere produktionsklar og performant måde:

let countries = Object.keys(cities).reduce((acc, k) =>  []; acc[country].push(k); return acc; , {});

Her bruger vi ikke spredningsoperator - det opretter et nyt array på hvert reducere () opkald, hvilket fører til en stor præstationsstraff: O (n²). I stedet for den gamle gode push () metode .

10. Opret en matrix med Fahrenheit-værdier ud fra en matrix med Celsius-værdier

Tænk på det som at behandle hvert element med en given formel?

const celsius = [-15, -5, 0, 10, 16, 20, 24, 32] const fahrenheit = celsius.map(t => t * 1.8 + 32); // fahrenheit is [5, 23, 32, 50, 60.8, 68, 75.2, 89.6]

11. Kod et objekt i en forespørgselsstreng

const params = {lat: 45, lng: 6, alt: 1000}; const queryString = Object.entries(params).map(p => encodeURIComponent(p[0]) + '=' + encodeURIComponent(p[1])).join('&') // queryString is "lat=45&lng=6&alt=1000"

12. Udskriv en tabel over brugere som kun en læsbar streng med angivne nøgler

Sometimes you want to print your array of objects with selected keys as a string, but you realize that JSON.stringify is not that great ?

const users = [ { id: 11, name: 'Adam', age: 23, group: 'editor' }, { id: 47, name: 'John', age: 28, group: 'admin' }, { id: 85, name: 'William', age: 34, group: 'editor' }, { id: 97, name: 'Oliver', age: 28, group: 'admin' } ]; users.map(({id, age, group}) => `\n${id} ${age} ${group}`).join('') // it returns: " 11 23 editor 47 28 admin 85 34 editor 97 28 admin"

JSON.stringify can make the string output more readable, but not as a table:

JSON.stringify(users, ['id', 'name', 'group'], 2); // it returns: "[ { "id": 11, "name": "Adam", "group": "editor" }, { "id": 47, "name": "John", "group": "admin" }, { "id": 85, "name": "William", "group": "editor" }, { "id": 97, "name": "Oliver", "group": "admin" } ]"

13. Find and replace a key-value pair in an array of objects

Let’s say we want to change John’s age. If you know the index, you can write this line: users[1].age = 29. However, let’s take a look at another way of doing it:

const updatedUsers = users.map( p => p.id !== 47 ? p : {...p, age: p.age + 1} ); // John is turning 29 now

Here instead of changing the single item in our array, we create a new one with only one element different. Now we can compare our arrays just by reference like updatedUsers == users which is super quick! React.js uses this approach to speed up the reconciliation process. Here is an explanation.

14. Union (A ∪ B) of arrays

Less code than importing and calling the lodash method union.

const arrA = [1, 4, 3, 2]; const arrB = [5, 2, 6, 7, 1]; [...new Set([...arrA, ...arrB])]; // returns [1, 4, 3, 2, 5, 6, 7]

15. Intersection (A ∩ B) of arrays

The last one!

const arrA = [1, 4, 3, 2]; const arrB = [5, 2, 6, 7, 1]; arrA.filter(it => arrB.includes(it)); // returns [1, 2]

As an exercise try to implement difference (A \ B) of the arrays. Hint: use an exclamation mark.

Thanks to Asmor and incarnatethegreat for their comments about #9.

That’s it!

If you have any questions or feedback, let me know in the comments down below or ping me on Twitter.

If this was useful, please click the clap ? button down below a few times to show your support! ⬇⬇ ??

Here are more articles I’ve written:

How to get started with internationalization in JavaScript

By adapting our app for different languages and countries, we provide a better user experience. It’s simpler for users…

Production ready Node.js REST APIs Setup using TypeScript, PostgreSQL and Redis.

For en måned siden fik jeg en opgave at opbygge en simpel søgning-API. Alt, hvad det skulle gøre, er at hente nogle data fra tredjepart ...

Tak for læsningen ❤️