Как уменьшить глубоко вложенный объект json путем объединения значений объектов

#javascript #arrays #json

Вопрос:

У меня есть вложенный объект json, подобный этому:

 [
  {
    "categoryId": "1",
    "subcategories": [
      {
        "categoryId": "2",
        "subcategories": [
          {
            "categoryId": "3",
            "subcategories": [
              {
                "categoryId": "4"
              },
              {
                "categoryId": "5"
              }
            ]
          },
          {
            "categoryId": "6"
          }
        ]
      }
    ]
  },
  { 
    // another category object
  }
]
 

Обратите внимание, что не все категории имеют подкатегории (некоторые категории имеют глубину 2 уровня, а некоторые-3 уровня).

Я хочу пройти по всему дереву и распечатать все categoryId в этой структуре (порядок не важен). т. е. вывод должен быть примерно таким: 1,2,3,4,5,6

Я придумал этот однострочный:

json.map(a => a.subCategories.map(b => b.subCategories ? b.subCategories.map(c => c.subCategories ? c.subCategories.map(d => d.categoryId) : c.categoryId) : b.categoryId)).join()

Но это не печать categoryId , содержащаяся в категориях верхнего уровня. Я также предпринял несколько попыток использовать reduce , но они были еще хуже. Не могли бы вы, пожалуйста, помочь мне это исправить. Спасибо.

Ответ №1:

Это в основном древовидная структура, вы можете рекурсивно перебирать ее по глубине-первый обход дерева

 let arr = [{
        "categoryId": "1",
        "subcategories": [{
            "categoryId": "2",
            "subcategories": [{
                    "categoryId": "3",
                    "subcategories": [{
                            "categoryId": "4"
                        },
                        {
                            "categoryId": "5"
                        }
                    ]
                },
                {
                    "categoryId": "6"
                }
            ]
        }]
    },
    {
        "categoryId": "1",
        "subcategories": [{
            "categoryId": "2",
            "subcategories": [
                {
                    "categoryId": "8"
                }
            ]
        }]
    }
]

let result = [];

let loop = (cat) => {
    if (cat.categoryId) result.push(cat.categoryId) // to handle first undefined
    if (!cat.subcategories || cat.subcategories.length === 0) return;

    cat.subcategories.forEach(cat => loop(cat));
}

let fakeRoot = {
    subcategories: arr
}; // create fake root

loop(fakeRoot) // initialise 
console.log(result) // all cordinates 
console.log([...new Set(result)]) // uniqe values