Рекурсивный оператор, проходит по вложенным объектам / массивам - но как он узнает, как это сделать? (JS Алгоритм) - PullRequest
0 голосов
/ 02 мая 2020

Вопрос

Мы пытаемся провести серию детей oop и вывести их имена на консоль. Но если у этих детей есть дети, мы должны их тоже напечатать.

У меня есть решение здесь:

function printChildrenRecursive(t){
  if(t.children.length === 0){
    return
   }
   t.choldren.forEach(child => {
    console.log(child.name)
    printChildrenRecusive(child)
    })
    }
    
 const tree = {
  name: 'John',
  children: [
    {
      name: 'Jim',
      children: []
      },
      {
        name: 'Zoe',
        children: [
          {name: 'Kyle, children: []},
          {name: 'Sophia, children: []}
          ]
         }
        }

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

Будем весьма признательны за упрощенное объяснение того, как это работает.

Ответы [ 3 ]

1 голос
/ 02 мая 2020

Как правило, вам придется просматривать вложенные данные не только для печати имен на консоль. По этой причине полезно разделить обход и вычислительный эффект -

const tree =
  {name:'John',children:[{name:'Jim',children:[]},{name:'Zoe',children:[{name: 'Kyle',children:[]},{name:'Sophia',children:[]}]}]}
  
const traverse = function* (node = {})
{ yield node
  if (node.children)
    for (const c of node.children)
      yield* traverse(c)
}

for (const node of traverse(tree)) // <-- traverse returns iterable
  console.log(node.name) // <-- console.log not part of traverse
  
// John
// Jim
// Zoe
// Kyle
// Sophia

Мы можем повторно использовать traverse для любого вида вычислений. Например, ниже мы используем заглавные буквы длиной более 3 символов -

const tree =
  {name:'John',children:[{name:'Jim',children:[]},{name:'Zoe',children:[{name: 'Kyle',children:[]},{name:'Sophia',children:[]}]}]}
  
const traverse = function* (node = {})
{ yield node
  if (node.children)
    for (const c of node.children)
      yield* traverse(c)
}

for (const node of traverse(tree))
  if (node.name.length > 3)
    console.log(node.name.toUpperCase())

// JOHN
// KYLE
// SOPHIA

Или мы можем собрать все имена в отсортированный массив -

const tree =
  {name:'John',children:[{name:'Jim',children:[]},{name:'Zoe',children:[{name: 'Kyle',children:[]},{name:'Sophia',children:[]}]}]}
  
const traverse = function* (node = {})
{ yield node
  if (node.children)
    for (const c of node.children)
      yield* traverse(c)
}

const allNames =
  Array.from(traverse(tree), node => node.name).sort()

console.log(allNames)
// [ 'Jim', 'John', 'Kyle', 'Sophia', 'Zoe' ]
1 голос
/ 02 мая 2020

В вашем коде было несколько опечаток. Я исправил их и встроил ваш код в файл HTML, см. Ниже, который работает для меня.

Вот страница HTML с вашим кодом (исправленные опечатки):

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<script>

    function printChildrenRecursive(t) {
        if (t.children.length === 0) {
            return;
        }
        t.children.forEach(child => {
            console.log(child.name)
            printChildrenRecursive(child)
        })
    }

    const tree = {
        name: 'John',
        children: [
            {
                name: 'Jim',
                children: []
            },
            {
                name: 'Zoe',
                children: [
                    {name: 'Kyle', children: []}, {name: 'Sophia', children: []}
                ]
            }]
    }

    printChildrenRecursive(tree);

</script>

</body>
</html>

А вот вывод консоли:

Jim
Zoe
Kyle
Sophia

Вы также попросили объяснения:

  • Определена функция printChildrenRecursive(t), которая принимает аргумент t. t может быть любым объектом (это JavaScript), но код будет предполагать, что t имеет определенные свойства, такие как t.children.
    • Сам код проверяет, имеет ли свойство t children свойство length со значением ноль. Если это так, функция завершится.
    • В противном случае для каждого из дочерних элементов t будет выполнена новая функция:
    • вывести имя дочернего элемента
    • выполнить функцию printChildrenRecursive и присвоить текущему child аргументу t.
  • Определена константа с именем tree, которая является объектом, содержащим пары ключ-значение, например, ключ name сопоставлен со значением 'John', а ключ children сопоставлен с массивом, который содержит больше объектов.
  • Строка printChildrenRecursive(tree) инициирует выполнение функции printChildrenRecursive(t) и назначает tree в качестве аргумента t.

Имеет ли это смысл?

0 голосов
/ 02 мая 2020
function printChildrenRecursive(object) {
  if (object.children.length > 0) {
   object.children.forEach((child) => {
    console.log(`${object.name}: ${child.name}`);
    printChildrenRecursive(child);
   });
  }
}

const object = {
  name: 'John',
  children: [
    {
      name: 'Jim',
      children: []
    },
    {
      name: 'Zoe',
      children: [
        {
          name: 'Kyle',
          children: []
        },
        {
          name: 'Sophia',
          children: []
        },
      ]
    }
  ]
};

printChildrenRecursive(object);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...