Typescript — Почему эта рекурсивная функция пропускает некоторые числа?

#json #angular #typescript

#json #angular #typescript

Вопрос:

С сервера я получаю этот объект JSON. Он представляет собой органиграмму компании и связанных с ней отделов.

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

Для этого я создал эту рекурсивную функцию. Это работает, но пропускает 3 отдела, которые размещены в другом отделе

Это файл JSON

 {
  "cd": 1,
  "cd_base": 0,
  "nome": "EMPRESA A",
  "children": [
    {
      "cd": 2,
      "cd_base": 1,
      "nome": "Departamento A",
      "children": [
        {
          "cd": 4,
          "cd_base": 2,
          "nome": "Serviço A1",
          "children": []
        },
        {
          "cd": 15,
          "cd_base": 2,
          "nome": "Serviço A2",
          "children": []
        }
      ]
    },
    {
      "cd": 3,
      "cd_base": 1,
      "nome": "Departamento B",
      "children": [
        {
          "cd": 7,
          "cd_base": 3,
          "nome": "Serviço B1",
          "children": []
        }
      ]
    },
    {
      "cd": 186,
      "cd_base": 1,
      "nome": "Departamento XX",
      "children": []
    }
  ]
}
  

И это функция в Typescript

 recursiveFunction(res: any): any[] {
    const numbers = new Array(); // to store the ID
    console.log('Im on '   res.cd   ' | '   res.nome);
    numbers.push(res.cd);
    if (res.children.length > 0) {
      console.log(res.cd   ' | '   res.nome   ' has children');
      res.children.forEach((row) => {
        numbers.push(row.cd);
        this.recursiveFunction(row);
      });
    } else {
      console.log(res.cd   ' | '   res.nome   ' doesn't have any children');
    }
    return numbers;
  }
  

И это возврат этой функции на консоль

 Im on 1 | EMPRESA A 
1 | EMPRESA A has c
Im on 2 | Departamento A 
2 | Departamento A has children 
Im on 4 | Serviço A1 
4 | Serviço A1 doesn't have any children 
Im on 15 | Serviço A2 
15 | Serviço A2 doesn't have any children 
Im on 3 | Departamento B 
3 | Departamento B has children 
Im on 7 | Serviço B1 
7 | Serviço B1 doesn't have any children 
Im on 186 | Departamento XX 
186 | Departamento XX doesn't have any children 
  

Затем я регистрирую массив чисел, и результатом является 1,2,3,186

  this.numbers.forEach(row => {
    console.log(row);
  });
 // 1, 2, 3, 186
  

Она добавляет CD 1, 2, 3 и 186, но пропускает 4, 7 и 15.
Все это ветвь / узел внутри другой ветви / узла

Чего я не понимаю? Рекурсивный способ — лучший способ сделать это? Есть ли более простой способ?

Приветствуется любая помощь

Комментарии:

1. 1. Ваша функция не является рекурсивной, потому что вы вызываете «recursiveCheckChildren» вместо «recursiveFunction». Пожалуйста, опубликуйте код «recursiveCheckChildren()», чтобы я мог показать вам проблему.

2. О, я вижу, на самом деле, это так, я изменился при написании вопроса — ‘ Я изменю вопрос. Спасибо, что указали на это

3. Вот решение вашей проблемы с рекурсивной функцией: stackblitz.com/edit/angular-cm2kqr

Ответ №1:

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

Хотя ответ @aonepathan работает, я бы избегал использования переменных вне области действия вашей функции.

Вместо этого все, что вам нужно сделать, это объединить результат функции с текущим массивом:

 recursiveFunction(res: any): any[] {
let numbers = new Array(); // to store the ID
console.log('Im on '   res.cd   ' | '   res.nome);
numbers.push(res.cd);
if (res.children.length > 0) {
  console.log(res.cd   ' | '   res.nome   ' has children');
  res.children.forEach((row) => {
    numbers = numbers.concat(this.recursiveFunction(row));
  });
} else {
  console.log(res.cd   ' | '   res.nome   ' doesn't have any children');
}
return numbers;
}
  

Другой вариант — передать массив чисел в вызовы вашей функции, и таким образом вы избавитесь от возврата:

 recursiveFunction(res: any, numbers: any[]) {
console.log('Im on '   res.cd   ' | '   res.nome);
numbers.push(res.cd);
if (res.children.length > 0) {
  console.log(res.cd   ' | '   res.nome   ' has children');
  res.children.forEach((row) => {
    this.recursiveFunction(row, numbers);
  });
} else {
  console.log(res.cd   ' | '   res.nome   ' doesn't have any children');
}
}
  

Первый раз, когда вы бы вызвали это, был бы с новым массивом:

 let result = new Array();
recursiveFunction(res, result);
doSomething(result);
  

Комментарии:

1. Большое спасибо! Как вы заявили, я также предпочитаю не использовать переменные вне области видимости, поэтому я выберу этот

2. согласен, переменная scoping и этот ответ более уместны!

Ответ №2:

Похоже, вы, возможно, повторно инициализировали массив чисел каждый раз, когда функция вызывается снова, рассмотрите возможность перемещения его за пределы функции:

 const numbers = new Array();

function recursiveFunction(res: any): any[] {
    console.log('Im on '   res.cd   ' | '   res.nome);
  numbers.push(res.cd);
    if (res.children.length > 0) {
      console.log(res.cd   ' | '   res.nome   ' has children');
      res.children.forEach((row) => {
        // numbers.push(row.cd);
        this.recursiveFunction(row);
      });
    } else {
      console.log(res.cd   ' | '   res.nome   ' doesn't have any children');
  }
    return numbers;
}
  

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

Консоль: 1, 2, 4, 15, 3, 7, 186

Комментарии:

1. Я немного отупел 🙂 Но спасибо. Это именно то, что мне было нужно 🙂