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)
  • Вопрос задан
  • 211 просмотров
Решения вопроса 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');

Рекурсии нет:

function getNestedProp(data, key) {
  const result = [];

  for (const stack = [ data ]; stack.length;) {
    const n = stack.pop();
    if (n instanceof Object) {
      if (n.hasOwnProperty(key)) {
        result.push(n[key]);
      }

      stack.push(...Object.values(n).reverse());
    }
  }

  return result;
}

// или

function getNestedProp(data, key) {
  const result = [];
  const stack = [];

  for (let i = 0, arr = [ data ]; i < arr.length || stack.length; i++) {
    if (i === arr.length) {
      [ i, arr ] = stack.pop();
    } else if (arr[i] instanceof Object) {
      if (arr[i].hasOwnProperty(key)) {
        result.push(arr[i][key]);
      }

      stack.push([ i, arr ]);
      [ i, arr ] = [ -1, Object.values(arr[i]) ];
    }
  }

  return result;
}
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
SilenceOfWinter
@SilenceOfWinter
та еще зажигалка...
почитай про рекурсивный вызов функций
Ответ написан
Ваш ответ на вопрос

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

Похожие вопросы