Як спростити свою базу коду за допомогою map (), зменшити () та фільтрувати () у JavaScript

Коли ви читаєте про Array.reduce і наскільки це круто, першим, а іноді і єдиним прикладом, який ви знайдете, є сума чисел. Це не наше визначення поняття "корисний". ?

Більше того, я ніколи не бачив цього в реальній кодовій базі. Але те, що я багато бачив, - це 7–8 рядкових операторів for-loop для вирішення звичайного завдання, де Array.reduce міг робити це в один рядок.

Нещодавно я переписав кілька модулів, використовуючи ці чудові функції. Мене здивувало, наскільки спрощена кодова база стала. Отже, нижче - список смаколиків.

Якщо у вас є хороший приклад використання карти або методу зменшення - опублікуйте його в розділі коментарів. ?

Давайте розпочнемо!

1. Видаліть дублікати з масиву чисел / рядків

Ну, це єдине, що стосується не мапи / зменшення / фільтрування , але воно настільки компактне, що важко було не включити його до списку. Крім того, ми також використаємо це в кількох прикладах.

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] - це значення ми надаємо як "звіт" на другій ітерації та так далі.

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]

Ми можемо трохи вдосконалити цей код, опустивши порожній масив []як другий аргумент для reduce (). Тоді перше значення вкладеного буде використовуватися як початкове значення відповідно . Дякую Володимиру Єфанову.

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

Зауважте, що використання оператора поширення всередині зменшення не є чудовим для продуктивності. Цей приклад є випадком, коли вимірювання продуктивності має сенс для вашого випадку використання. ☝️

Завдяки Павлу Волаку , ось коротший шлях без 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}

Дякуємо Саї Крішні за пропозицію цього!

7. Індексація масиву об’єктів (таблиця пошуку)

Замість того, щоб обробляти весь масив для пошуку користувача за ідентифікатором, ми можемо побудувати об'єкт, де ідентифікатор користувача представляє ключ (з постійним часом пошуку).

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; , {});

Тут ми не використовуємо оператор поширення - він створює новий масив при кожному виклику reduce () , що призводить до великого покарання за продуктивність: 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 ❤️