Как вытащить свойство из массива древовидных объектов в js?

107
08 апреля 2021, 20:20

Вопрос:как создать массив из title'ов?

let sells = [
   {
    id: 1,
    title: 'apple',
    goods: {
            id: 2,
            title: 'orange',
            goods: {
                    id: 3,
                    title: 'cucumber',
                    goods: {
                            id: 4,
                            title: 'pumpkin',
                           }
                   }
           }
   }
]
Answer 1

Да, все верно, поможет рекурсия, я еще предположил что на верхнем уровне может быть не один объект, иначе не ясно засем тут массив очутился:

let sells = [ 
   { 
    id: 1, 
    title: 'pineapple', 
    goods: { 
            id: 2, 
            title: 'grapes', 
            goods: { 
                    id: 3, 
                    title: 'watermelon', 
                    goods: { 
                            id: 4, 
                            title: 'guava', 
                           } 
                   } 
           } 
   }, 
   { 
    id: 1, 
    title: 'apple', 
    goods: { 
            id: 2, 
            title: 'orange', 
            goods: { 
                    id: 3, 
                    title: 'cucumber', 
                    goods: { 
                            id: 4, 
                            title: 'pumpkin', 
                           } 
                   } 
           } 
   } 
]; 
 
let collect = (s, acc) => { 
 
  // если у объекта есть сво-во title поместим его в аккумулятор 
  s.title && acc.push(s.title); 
   
  // если у объекта есть сво-во goods вызовем для него collect,  
  //но передадим туда не пустой массив в качестве аккумулятора,  
  //а тот, кторый был уже передан в эту функцию 
  s.goods && collect(s.goods, acc); 
   
  // возвращаем аккумулятор 
  return acc; 
}; 
// flatMap по сути превращает массив массивов в плоский массив 
// для всех объектов первого уровня вызываем функцию collect и  
// передаем туда пустой массив в качестве аккумулятора 
let result = sells.flatMap(s => collect(s, [])); 
console.log(result);

Вот вариант с reduce, функция collect не отличается от сниппета выше, разница в том, что создается только один результирующий массив, а не по кол-ву элементов верхнего уровня...

let sells = [ 
   { 
    id: 1, 
    title: 'pineapple', 
    goods: { 
            id: 2, 
            title: 'grapes' 
    } 
   }, 
   { 
    id: 1, 
    title: 'apple' 
   } 
]; 
 
let collect = (s, acc) => { 
  s.title && acc.push(s.title); 
  s.goods && collect(s.goods, acc); 
  return acc; 
}; 
 
let result = sells.reduce((acc, el) => collect(el, acc), []); 
console.log(result);

Answer 2

В случае если нет возможности использовать рекурсию, например при очень большой вложенности, можно использовать цикл:

function collect(good){
    var goods = [good.title];
    while(good.goods){
        good = good.goods;
        goods.push(good.title);
    }
    return goods;
}

Далее использовать данную функцию также как в ответе @Stranger in the Q

READ ALSO
Кому задавать атрибуты, потомку или родителю?

Кому задавать атрибуты, потомку или родителю?

Какая структура с точки зрения CSS правильная? Вариант 1:

99
Как отобразить булеты строк в richedit?

Как отобразить булеты строк в richedit?

Поддерживает ли richedit "внешние" булеты, можно ли ими управлять? (ну как в notepad++ кругляшок возле нумерации строк) Пример создания контрола ниже

88
сборка и запуск проекта на AstraLinux

сборка и запуск проекта на AstraLinux

Возникает ошибка при сборке проекта на AstraLinux

102
Класс type_info

Класс type_info

Записать в файл имя функции, версию и параметрЕсли с того момента исходный код функции изменился, вернуть сообщение что "версия функций не совпадают"

88