g-unit
@g-unit

Вложенное дерево — как достать все id?

Есть такая структура данных:

const data = [
    {
        id: 0,
        children: [
            { id: '0_1' }, 
            { id: '0_2' }
        ]
    },
    {
        id: 1,
        children: [
            {
                id: '1_1',
                children: [
                    { id: '1_1_1' }, 
                    { id: '1_1_2' }
                ]
            }, 
            { id: '1_2' }
        ]
    }
]

Моя задача собрать все id, которые находятся внутри children, в том порядке в котором они идут в этом дереве.
Вложенность может быть любая, как и значение у id (строка или число).
В целом у меня это получилось, но мне не совсем нравится мой код, как его можно улучшить?
function getChildrenIds(arr) {
  return arr.reduce((acc, child) => {
    if (!child.children) {
      acc.push(child)
    }
    else if (!child.children.some(child => child.children)) {
      acc.push(child.children)
    } else {
      const deepChildren = getChildrenIds(child.children);
      return [...acc, ...deepChildren]
    }

    return acc.flat();
    // Пытался вернуть все id такой записью: 
    // return acc.flat(Infinity).map(({ id }) => id);
  }, [])
}

const ids = getChildrenIds(data, 'children').map(({ id }) => id)
console.log(ids) // ["0_1", "0_2", "1_1_1", "1_1_2", "1_2"]

К примеру, мне не нравится
  • куча условий (но без них не представляю как это написать)
  • не могу сразу вернуть массив всех id внутри функции (вместо этого отдельно вынужден использовать map)
  • Вопрос задан
  • 184 просмотра
Решения вопроса 1
0xD34F
@0xD34F Куратор тега JavaScript
const getNestedProp = (data, key) => Object
  .entries(data instanceof Object ? data : {})
  .reduce((acc, [ k, v ]) => (
    (k === key) && acc.push(v),
    acc.push(...getNestedProp(v, key)),
    acc
  ), []);


const ids = getNestedProp(data.flatMap(n => n.children), 'id');

Или, более специализированный вариант (для данных указанной структуры, а не произвольных):

const getIds = arr =>
  (Array.isArray(arr) ? arr : []).reduce((acc, n) => (
    acc.push(n.id, ...getIds(n.children)),
    acc
  ), []);


const ids = getIds(data.flatMap(n => n.children));
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
SilenceOfWinter
@SilenceOfWinter
та еще зажигалка...
почитай про рекурсивный вызов функций
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы