Помощь с JS и функцией reduce
Не совсем понимаю, как работать с этой функцией. С простыми примерами еще да, а если сложнее, то путаюсь. Есть массив объектов - учащиеся, с полями (имя, оценка, класс). Нужно найти топ 5 учеников среди учащихся, отсортированных по полю имя.
Ответы (1 шт):
Метод reduce у массива обычно применяется для нахождения общего результирующего значения, по типу нахождения среднего балла по классу или суммы всех оценок у учеников. Для данной вам задачи более эффективным решением, как по мне, было бы через сам цикл for, но никак не reduce.
Механизм работы метода reduce: Этот метод принимает в себя 2 параметра. Первый это callback функция(о ней чуть позже), второй параметр это начальное значение результирующего значения (для вашей задачи раз уж результирующее значение это массив, то изначальное значение будет пустой массив).
Callback функция в методе reduce. У этой функции есть 4 параметра, но разберём первые 2. 1ый -accumulator. Аккумулятор, аккумулирующий значение, которое возвращает функция callback после посещения очередного элемента, либо значение initialValue, если оно предоставлено. То есть это начальное значение или же результат который вернуло предыдущее выполнение callback. 2-ой параметр по очереди получает элементы массива.
Таким образом можем посмотреть, чему равно выполнение reduce на каждой итерации:
const arr = [2,3,4,5,6,7,8,9]
const res = arr.reduce(function(a,b,i){
console.log(`${i} acc:${a}; curr:${b};`)
console.log(`return ${a*b*2}`)
return a*b*2
},1)
console.log(res)
console.log(arr)
Можно заметить, что сам массив при этом не изменяется.
Решение вашей задачи при помощи reduce. Честно говоря код очень плохой, присутствует даже дубляж кода, а другого результата и не следовало ожидать ведь reduce не предназначен для сортировок.
class Student{
constructor(name,mark,className){
this.name=name
this.mark=mark
this.class=className
}
}
const students = [
new Student('Влад',1,'1A'),
new Student('Маша',2,'1A'),
new Student('Аня',3,'1A'),
new Student('Марина',4,'1A'),
new Student('Кирил',5,'1A'),
new Student('Данил',6,'1A'),
new Student('Шац',7,'1A'),
new Student('Александр',8,'1A')
]
const res = students.reduce((a,b)=>{
if(a.length<5){
//вставка студента с соблюдением сортировки по имени
let i
for(i=0;i<a.length;i++){
if(a[i].name.localeCompare(b.name)>0){
break
}
}
a.splice(i,0,b)
//
return a
}
let minMark =Math.min(...a.map(st=>st.mark))
if(minMark<b.mark){
let minIndex =a.findIndex(st=>{
return st.mark === minMark
})
a.splice(minIndex,1)
//вставка студента с соблюдением сортировки по имени
let i
for(i=0;i<a.length;i++){
if(a[i].name.localeCompare(b.name)>0){
break
}
}
a.splice(i,0,b)
//
return a
}
return a
},[])
console.log(res)
Более простой и "красивый" способ, с использованием других методов массива:
class Student{
constructor(name,mark,className){
this.name=name
this.mark=mark
this.class=className
}
}
const students = [
new Student('Влад',1,'1A'),
new Student('Маша',2,'1A'),
new Student('Аня',3,'1A'),
new Student('Марина',4,'1A'),
new Student('Кирил',5,'1A'),
new Student('Данил',6,'1A'),
new Student('Шац',7,'1A'),
new Student('Александр',8,'1A')
]
const topStud = students.sort((a,b)=>b.mark-a.mark).slice(0,5)
console.log(topStud.sort((a,b)=>a.name.localeCompare(b.name)))