Как да опростите вашата кодова база с map (), намаляване () и филтриране () в JavaScript

Когато четете за Array.reduce и колко готино е, първият и понякога единственият пример, който намирате, е сумата от числата. Това не е нашето определение за „полезно“. ?

Освен това никога не съм го виждал в истинска кодова база. Но това, което много съм виждал, е 7-8 редове for-loop изявления за решаване на обикновена задача, където Array.reduce може да го направи в един ред.

Наскоро пренаписах няколко модула, използвайки тези страхотни функции. Изненада ме колко опростена стана кодовата база. И така, по-долу е даден списък с екстри.

Ако имате добър пример за използване на карта или метод за намаляване - публикувайте го в раздела за коментари. ?

Да започваме!

1. Премахнете дубликати от масив от числа / низове

Е, това е единственият, който не е за map / reduce / filter , но е толкова компактен, че беше трудно да не го включите в списъка. Плюс това ще го използваме и в няколко примера.

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

2. Лесно търсене (чувствително на малки и големи букви)

Методът filter () създава нов масив с всички елементи, които преминават теста, изпълнен от предоставената функция.

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. Лесно търсене (без регистрация)

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

4. Проверете дали някой от потребителите има права на администратор

Методът some () тества дали поне един елемент в масива преминава теста, изпълнен от предоставената функция.

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

5. Изравняване на масив от масиви

Резултатът от първата итерация е равен на: [... [], ... [1, 2, 3]] означава, че се трансформира в [1, 2, 3] - тази стойност ние предоставяме като 'acc' за втората итерация и скоро.

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]

Можем леко да подобрим този код, като пропуснем празен масив []като втори аргумент за намаляване (). Тогава първата стойност на вложеното ще бъде използвана като първоначална стойност съгласно . Благодаря на Владимир Ефанов.

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

Имайте предвид, че използването на оператора за разпространение вътре в намаляване не е чудесно за производителност. Този пример е случай, когато измерването на ефективността има смисъл за вашия случай на употреба. ☝️

Благодарение на Paweł Wolak, тук е по-кратък начин без Array.reduce:

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

Също Array.flat е идва, но тя все още е експериментална функция.

6. Създайте обект, който съдържа честотата на посочения ключ

Нека да групираме и преброим свойството 'age' за всеки елемент в масива:

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}

Благодаря на sai krishna, че предложи това!

7. Индексиране на масив от обекти (справочна таблица)

Вместо да обработваме целия масив за намиране на потребител по id, можем да изградим обект, където id на потребителя представлява ключ (с постоянно време за търсене).

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' } }

Полезно е, когато трябва да получавате достъп до данните си като идентификатор uTable[85].nameмного.

8. Извлечете уникалните стойности за дадения ключ на всеки елемент от масива

Нека създадем списък със съществуващите групи потребители. Методът map () създава нов масив с резултатите от извикването на предоставена функция за всеки елемент в извикващия масив.

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

9. Обръщане на карта ключ-стойност на обекта

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"] }

Тази еднопластова линия изглежда доста сложна. Тук използваме оператора запетая и това означава, че връщаме последната стойност в скоби - acc. Нека препишем този пример по по-готов за производство и по-ефективен начин:

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

Тук не използваме оператор за разпространение - той създава нов масив при всяко извикване за намаляване () , което води до голямо наказание за производителност: O (n²). Вместо това стария добър метод push () .

10. Създайте масив от стойности по Фаренхайт от масив от стойности на Целзий

Мислете за това като за обработка на всеки елемент с дадена формула?

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. Кодирайте обект в низ за заявка

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. Отпечатайте таблица с потребители като четим низ само с посочени ключове

Понякога искате да отпечатате масива си от обекти с избрани ключове като низ, но осъзнавате, че JSON.stringify не е толкова страхотен?

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 може да направи изхода на низа по-четлив, но не като таблица:

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. Намерете и заменете двойка ключ-стойност в масив от обекти

Да кажем, че искаме да променим възрастта на Джон. Ако знаете, че индексът, можете да напишете този ред: users[1].age = 29. Нека обаче разгледаме друг начин за това:

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

Тук, вместо да променяме единичния елемент в нашия масив, ние създаваме нов само с различен елемент. Сега можем да сравним нашите масиви само чрез препратка, като updatedUsers == usersтова е супер бързо! React.js използва този подход, за да ускори процеса на помирение. Ето обяснение.

14. Съединение (A ∪ B) на масиви

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.

A month ago I was given a task to build a simple Search API. All It had to do is to grab some data from 3rd party…

Thanks for reading ❤️