map(), filter() и reduce() в JavaScript
Код на JavaScript можно сделать более функциональным, попутно облегчив труд программиста. Знакомимся с методами массивов map(), filter() и reduce(). Обсудить Перевод публикуется с сокращениями, автор оригинальной статьи Aditya Dhanraj Tiwari. Методы массивов map, filter и reduce – по сути, лишь некоторые из наиболее известных и простых в использовании функций высшего порядка, которые обеспечивают обратный вызов для каждого элемента. В этой статье мы рассмотрим, как применение map(), filter() и reduce() поможет сделать код: Приступим к рассмотрению. Примечание переводчика Обратный вызов позволяет в функции исполнять заданный в аргументе код, который может быть недоступен для прямого вызова. Часто такой подход используется для реализации алгоритма обхода некого хранилища объектов и определенных действий с его элементами. Функция высшего порядка может принимать в качестве аргументов другие функции или возвращать функцию в качестве результата. В этом случае функции имеют тот же статус, что и прочие объекты данных. Такой подход позволяет делать сложные программы компактными. Array.map() Представим ситуацию, в которой есть несколько записей для студентов с атрибутами: name, ID и marks. Постановка задачи: получить имена студентов и записать их заглавными буквами. Ожидаемый результат: Существует несколько способов достижения цели: Во всех вышеупомянутых примерах создается пустой массив для хранения результата. Как в Решение с помощью map() Приведенный выше фрагмент кода показывает, насколько лаконичным становится синтаксис, когда используется метод map и не нужно определять пустой массив. Работа map(): Метод map() принимает два аргумента: функцию обратного вызова и необязательное значение объекта. Обратный вызов map() выполняется для каждого элемента исходного массива и возвращает новое значение в результирующий. Если thisValue не задано, функция обратного вызова будет привязана к объекту, который ее вызвал (это значение зависит от выражения вызывающего объекта). В нашем примере thisValue будет привязываться к studentRecords. Array.filter() filter() возвращает только те элементы из массива, которые удовлетворяют заданным критериям. Постановка задачи: предположим, что у нас есть тот же набор данных, что и выше, но на этот раз мы хотим получить подробную информацию о студентах, набравших более 50 баллов. Ожидаемый результат: Решение: используем filter() для выбора записей, удовлетворяющих заданному условию (т. е. больше 50 баллов). Постановка задачи: получить информацию о студентах, набравших более 50 баллов и имеющих id больше 120. Решение: как показано в приведенном выше фрагменте кода, используя filter() с несколькими условиями для фильтрации данных, мы можем эффективно справиться с задачей. Работа filter(): filter() принимает функцию обратного вызова, которая возвращает значение bool. Если она возвращает true, то объект добавляется в результирующий массив. В противном случае объект игнорируется. Array.reduce() Точно так же, как map() и filter(), reduce() выполняет обратный вызов для каждого элемента массива. Чтобы лучше понять reduce, сначала нужно рассмотреть два термина: «accumulator» и «reducer». Accumulator – это значение, которое мы получаем в конечном итоге, а reducer – действие, которое следует выполнить для его получения. Важно помнить, что reducer всегда будет возвращать только одно значение. Постановка задачи: на этот раз необходимо знать общую сумму баллов студентов. Решение: Работа reduce(): Давайте разберемся в работе reducer шаг за шагом: Чтобы сравнить наши знания с фактической работой reduce(), рассмотрим значения «accumulator» и «curr_value» для каждой итерации из приведенного выше примера. Из журнала видно, что accumulator начинается со значения 0 и на каждом шаге его значение обновляется суммой «previous value» и «curr_value». Теперь объединим возможности map(), filter() и reduce() Постановка задачи: на этот раз мы хотим получить только имена студентов, набравших более 50 баллов из того же набора данных. Решение: сначала мы отфильтровали данные с помощью filter(), а затем использовали map(), чтобы получить только атрибут name. Примечание: Вы можете связать map() и filter(), так как они возвращают массивы. Постановка задачи: напечатаем сумму баллов студентов с id больше 120. Решение: сначала выбрали студентов с идентификатором больше 120 с помощью filter(), а потом передали отфильтрованный массив студентов в reduce(), чтобы получить сумму их баллов. Примечание: вы можете связать reduce() после map() и filter(), поскольку они возвращают массивы, но не можете связать map() и filter() после reduce(), т. к. он возвращает единственное значение. Постановка задачи: вывести общее количество студентов с баллами больше 50, полученными после начисления поощрения в 15 баллов. Решение: Заключение В этом гайде мы разобрались, как map(), filter() и reduce() могут облегчить жизнь разработчику, сократив количество ненужных явных циклов и объявлений пустых массивов. Это сделает код более функциональным и легким для понимания. Попробуйте заменять циклы этими методами всякий раз, когда у вас появится такая возможность. Удачи! Дополнительные материалы:
let studentRecords = [ {name: 'John', id: 123, marks : 98 }, {name: 'Baba', id: 101, marks : 23 }, {name: 'yaga', id: 200, marks : 45 }, {name: 'Wick', id: 115, marks : 75 } ]
['JOHN', 'BABA', 'YAGA', 'WICK']
1. for() loop let names = []; for (let index = 0; index < studentRecords.length; index++){ names.push(studentRecords[index].name.toUpperCase()); } console.log(names); // logs: [ 'JOHN', 'BABA', 'JOHN', 'WICK' ] 2. for(...of) let names = [] for (const student of studentRecords) { names.push(student.name.toUpperCase()); } console.log(names); // logs: [ 'JOHN', 'BABA', 'JOHN', 'WICK' ] 3. forEach() let names = [] studentRecords.forEach( student => { names.push(student.name.toUpperCase()); }) console.log(names); // logs: [ 'JOHN', 'BABA', 'JOHN', 'WICK' ]
for(...of)
, так и в for()
нужно явно перебирать массивы, что делает код более запутанным.
let names = studentRecords.map( stu => stu.name.toUpperCase()); console.log(names); // logs: [ 'JOHN', 'BABA', 'JOHN', 'WICK' ]
Array.map( callback, thisValue )
[{name: 'John', id: 123, marks : 98 },{name: 'Wick', id: 115, marks : 75 }]
let names = studentRecords.filter(stu => stu.marks > 50); console.log(names); // logs: [ { name: 'John', id: 123, marks: 98 },{ name: 'Wick', id: 115, marks: 75 }]
let names = studentRecords.filter(stu => stu.marks > 50 && stu.id > 120) console.log(names); //logs: [ { name: 'John', id: 123, marks: 98 } ]
let totalMarks = studentRecords.reduce( ((acc,emp) => acc+emp.marks), 0) console.log(totalMarks);// logs: 241
Array.reduce( (accumulator,curr_value) => expression ), intialValue)
let totalMarks = studentRecords.reduce( function(accumulator,curr_value){ console.log(`accumulator: ${accumulator}, curr_value:$ curr_value.marks}`); return accumulator + curr_value.marks;}, 0) console.log(totalMarks); // logs ------- accumulator: 0 , curr_value: 98 accumulator: 98 , curr_value: 23 accumulator: 121 , curr_value: 45 accumulator: 166 , curr_value: 75 241
Пример 1. map() и filter()
let names = studentRecords.filter(stu => stu.marks > 50).map(stu => stu.name) console.log(names); // logs: [ 'John', 'Wick' ]
Пример 2. filter() и reduce()
let totalMarks = studentRecords.filter(stu => stu.id > 120).reduce((acc,curr) => acc + curr.marks ,0) console.log(totalMarks); // logs: 143
Пример 3. map(), filter() и reduce()
let studentRecords = [ {name: 'John', id: 123, marks : 98 }, {name: 'Baba', id: 101, marks : 23 }, {name: 'John', id: 200, marks : 45 }, {name: 'Wick', id: 115, marks : 75 }, ] let totalMarks = studentRecords.map(function(stu){ if(stu.marks < 50){ stu.marks += 15;} return stu; }).filter(stu => stu.marks > 50).reduce((acc,curr) => acc+curr.marks, 0); console.log(totalMarks); //logs : 233
- 1 views
- 0 Comment
Свежие комментарии