Что означает нижнее подчеркивание в конце reduce?
Разбираю код
const data = [
{
continent_name: "Asia",
country_name: "Iran",
subdivision_1_name: "Chaharmahal and Bakhtiari Province",
city_name: "Lir Abi"
},
{
continent_name: "Europe",
country_name: "Cyprus",
subdivision_1_name: "Ammochostos",
city_name: "Protaras"
},
{
continent_name: "Asia",
country_name: "Iran",
subdivision_1_name: "West Azerbaijan Province",
city_name: "Post"
},
{
continent_name: "Africa",
country_name: "Somalia",
subdivision_1_name: "Bakool",
city_name: "Oddur"
}
],
keys = ["continent_name", "country_name", "subdivision_1_name", "city_name"],
result = data.reduce(
(r, o) => {
keys.reduce(function (q, k) {
const label = o[k];
if (!q[label]) q._.push({ label, children: (q[label] = { _: [] })._ });
return q[label];
}, r);
return r;
},
{ _: [] }
)._;
Как работает вот это последняя строка )._;?
Если он возвращает [] вот этот массив, то почему мой код не работает?
const numbers = [1,2,3,4,5];
const a = numbers.reduce((a, c) => a._ += c, { _: 5 })._;
Получаю ошибку
Cannot create property '_' on number '6'
Ответы (1 шт):
Приведу описание того насколько я понял текущую логику.
TD;DR Вкратце _ - это генерируемый в редюсере ключ, который заполняется всеми элементами изначального массива, т.е. в свою очередь подвергаются иерархичному вкложению исходя из массива keys и объединению схожих ключей. (В данном случае имеются не сами ключи, а их значения)
Так же доработал ваш пример кода, в данном случае нужно учесть что срелочная функция редюсера возвращает аккумулятор, но вы пытались вернуть число у которого нет свойства _. Все что я сделал - использовал оператор запятая, чтобы вернуть именно аккумулятор, для того чтобы парсер не ругался я обернул результат стрелочной функции в скобки.
const numbers = [1,2,3,4,5];
const a = numbers.reduce((a, c) => (a._ += c, a ), { _: 5 })._;
console.log(a)
Подробнее:
Мы видим что в качестве начального результатаредюсера передается объект со свойством _ которое равно пустому массиву в коде так:
result = data.reduce((r, o) => {
...................
}
{ _: [] } <------ начальный результат
)
назовем это RESULT.
Чем по итогу будет _.
Для начала установим что он будет ключем r (аккумулятор), напомню это тот самый { _: [] } или RESULT
Далее мы видим вложенный редюсер который в который через область видимости передается опять тот самый r или RESULT,
но уже под именем q в качестве начального значения аккумулятора.
result = data.reduce((r, o) => { -----,
keys.reduce(function (q, k) |
}, r); <-------------------------`
........................
},
{ _: [] }
)._;
Этот внутренний редюсер отвечает за то чтобы преобразовать
элементы data в объекты. Массив keys служит правилом иерархии этого объекта. Каждый элемент keys будет вложен в предыдущий. Как упоминалось выше работа идет со значениями.
например: "continent_name" это текущийЭлементData['continent_name']
Мы видим как заполняется _, примерно так:
_.push(label, children:[])
условие if проверяет если значение по ключу из keys (label) в RESULT отсутствует то в массив ключа _ пушится элемент, содержащий label и еще массив дочерних элементов:
children: (q[label] = { _: [] })._
(слелдует отметить что тут _ не то которое мы обсуждаем, более того его назначение мне не понятно, поэтому не заостряю на нем внимание, тем не менее, полагаю что вместо _ тут больше бы подошло так же children)
Что тут происходит, q[label] приравнивается { _: [] } как известно операция присваивания возвращает результат присваивания таким образом это объект { _: [] } из которого мы потом выбираем значение по ключу _ что есть пустой массив.
Таким образом в условии if происходит сразу 2 вещи
- q._.push(...) вставка в ключ
_вRESULT - q[label]= .... присваивание ключу в
RESULTпо имени из значенийkeys
Встроенный редюсер возвращает q[label] т.е. вложенное свойство q а не сам q (напомню что q - это r таким образом происходит вкладывание свойств друг в друга.
В итоге
По ключам верхнего уровня "continent_name" формируются смерженные объекты с вложенностью друг в друга (вспоминаем q[label]) которые в свою очередь попадают в ключ верхнего уровня _, который изначально был пустым массивом.