Рекурсивно получить всех детей

Мне нужно рекурсивно получить всех детей от вложенного объекта. Я уже написал функцию, которая это делает (вроде как), но я думаю, что ее можно улучшить.

Как сделать его короче и чище?

Я включил данные, которые использую для тестирования, а также написанную мной функцию, которую нужно улучшить.

let data = [{
    id: 1,
    child: {
      id: 2,
      child: {
        id: 3,
        child: {
          id: 4,
          child: null
        }
      }
    }
  },
  {
    id: 5,
    child: {
      id: 6,
      child: null
    }
  }
];


// function

for (let cat of data) {
  cat.children = getCategoryChild(cat);
  console.log(cat.children)
}

function getCategoryChild(cat) {
  let t = [];

  if (cat.child != null) {
    t.push(cat.child);

    let y = getCategoryChild(cat.child);
    if (y.length > 0) {
      for (let i of y) {
        t.push(i)
      }
    }
  }

  return t;
}

Ожидаемый результат:

[{id: 1, children: [{id: 2}, {id: 3}, {id: 4}]}, {id: 5, children: [{id: 6}]}]


person Carla    schedule 12.02.2019    source источник
comment
Uncaught SyntaxError: Unexpected identifier и после того, как вы исправите запятую там Uncaught TypeError: Cannot read property 'data' of undefined, кажется, в данный момент не работает   -  person CertainPerformance    schedule 12.02.2019
comment
@Carla, ты хочешь, чтобы все дети были в одномерном массиве?   -  person Maheer Ali    schedule 12.02.2019
comment
@CertainPerformance Я исправил проблему.   -  person Carla    schedule 12.02.2019
comment
у каждой категории есть только один ребенок? Код подразумевает, что да, я просто хочу в этом убедиться   -  person Leroy Stav    schedule 12.02.2019
comment
@Carla покажи ожидаемый результат.   -  person Maheer Ali    schedule 12.02.2019
comment
Поскольку вы просите помощи в улучшении рабочего кода, это может быть лучше для codereview.stackexchange.com, но не забудьте взять их обзор и сначала прочтите их справку, особенно О каких темах я могу здесь спросить?   -  person Şivā SankĂr    schedule 12.02.2019
comment
Я уже написал функцию, которая делает это (типа) Что вы подразумеваете под типа? Можете ли вы включить ожидаемый результат в вопрос? В чем проблема с кодом?   -  person guest271314    schedule 12.02.2019
comment
@ guest271314 На самом деле это работает нормально.   -  person Carla    schedule 12.02.2019
comment
Да, вы, вероятно, можете сократить код. Не уверен, что означает очиститель. Непонятно, каков ожидаемый результат. Если в коде нет проблем, рассмотрите возможность задать вопрос на обзоре кода codereview.stackexchange.com, включая описание того, что делает код, и ожидаемый результат в теле вопроса. См. stackoverflow.com/help/how-to-ask, stackoverflow.com/help/mcve.   -  person guest271314    schedule 12.02.2019
comment
у вас есть некоторые дочерние массивы внутри?   -  person Nina Scholz    schedule 12.02.2019
comment
@NinaScholz Чего я хочу: [{id: 1, children: [{id: 2}, {id: 3}, {id: 4}]}, {id: 5, children: [{id: 6}]}]   -  person Carla    schedule 12.02.2019


Ответы (4)


предполагая, что у каждой категории есть только один дочерний элемент

отредактировано, чтобы придерживаться ожидаемого результата...

function iterChildren(cat) {
  let c = cat, children = [];

  while (c.child) {
    children.push({id: c.child.id});
    c = c.child;
  }

  return {id: cat.id, children: children};
}

let newData = data.map(iterChildren);
person Leroy Stav    schedule 12.02.2019
comment
Мне нравится этот метод. Очень просто и лаконично. - person Carla; 12.02.2019

Вы можете использовать рекурсивный подход, проверив фактическое свойство child

function convert(array) {
    const iter = o => o ? [{ id: o.id }, ...iter(o.child)] : [];
    return array.map(({ id, child }) => ({ id, children: iter(child) }));
}

var data = [{ id: 1, child: { id: 2, child: { id: 3, child: { id: 4, child: null } } } }, { id: 5, child: { id: 6, child: null } }];

console.log(convert(data));
.as-console-wrapper { max-height: 100% !important; top: 0; }

person Nina Scholz    schedule 12.02.2019
comment
Не то, что я хочу. Я хочу что-то вроде [{id: 1, children: [{id: 2}, {id: 3}, {id: 4}]}, {id: 5, children: [{id: 6}]}] - person Carla; 12.02.2019
comment
Я отредактировал вопрос и добавил ожидаемый результат. - person Carla; 12.02.2019
comment
Это здорово, но почти неразборчиво для начинающего разработчика :-) использует слишком много новомодных продвинутых концепций - person Leroy Stav; 12.02.2019

Я переписал эту функцию.
Она фильтрует кошек и возвращает только объекты с id и child_id каждой из них.

let output = [],
    data = [{
        id: 1,
        child: {
          id: 2,
          child: {
            id: 3,
            child: {
              id: 4,
              child: null
            }
          }
        }
      },
      {
        id: 5,
        child: {
          id: 6,
          child: null
        }
      }
    ];

function getCategoryChild(cat) {
  var t = [{
    id: cat.id,
    child_id: null
    /* HERE you can set, what kind of data should be included to output */
  }]
  if (cat.child) {
    t[0].child_id = cat.child.id
    t = t.concat(getCategoryChild(cat.child))
  }
  return t
}

for (x of data) {
  output=output.concat(getCategoryChild(x))
}

console.log(output)

РЕДАКТИРОВАТЬ: я отредактировал свой код, предполагая, что у одной кошки может быть больше детей:

let output = [],
  data = [{
      id: 1,
      child: {
        id: 2,
        child: {
          id: 3,
          child: {
            id: 4,
            child: null
          }
        }
      }
    },
    {
      id: 5,
      child: {
        id: 6,
        child: null
      }
    },
    {
      id: 7,
      child: [
        {
          id: 8,
          child: {
            id: 9,
            child: null
          }
        }, 
        {
          id: 10,
          child: null
        }, 
        {
          id: 11,
          child: null
        }
      ]
    },
  ];

function getCategoryChild(cat) {
  var t = [{
    id: cat.id,
    child_id: []
    /* HERE you can set, what kind of data should be included to output */
  }]
  if (cat.child) {
    if (!(cat.child instanceof Array)) {
      cat.child = [cat.child]
    }
    for (var x of cat.child) {
      t[0].child_id.push(x.id)
      t = t.concat(getCategoryChild(x))
    }
  }
  return t
}

for (x of data) {
  output = output.concat(getCategoryChild(x))
}

console.log(output)

person FZs    schedule 12.02.2019

person    schedule
comment
Пожалуйста, добавьте некоторое объяснение к этому коду, чтобы OP мог узнать, что он делает. - person Nico Haase; 12.02.2019
comment
@Карла короче (;c;c=c.child)yield{id:c.id} - person guest271314; 12.02.2019