Как пройти через элементы массива или свойства объекта для рекурсивных функций - PullRequest
2 голосов
/ 21 марта 2020

Прошу прощения, если это глупый вопрос. Я не могу найти какие-либо ресурсы через Google, которые go через эту топи c. Я не понимаю, как пройти через массив свойств объекта в рекурсивной функции, поскольку по определению рекурсия будет проходить через себя. Я знаю, как перебирать массив без для l oop в рекурсии. Чего я не понимаю, так это как l oop через объект для рекурсии. Это всего лишь некоторый код, который я придумал, чтобы продемонстрировать свое непонимание.

var input1 = [1, 2, 3, 4, 5];
var input2 = {1: 'a', 2: 'b', 3: 'c'};

//for arrays
var arrayRecursion = function(someArray) {
  var result = [];

  //base case
  if (someArray.length === 0) {
    return result;
  } else {
    result.push(someArray.slice(0, 1));
    return result.concat(arrayRecursion(someArray.slice(1)));
  }
}

//for objects trying to copy input into results
var objectRecursion = function(someObject) {
  var result = {};

  for (var value in someObject) {
  //base case
  if (typeof(someObject[key]) !== 'object') {
      return result;
  }
  //recursion
  }
}

Главный вопрос, который у меня есть, касается моей рекурсии объекта. Если у меня есть установлен для - в l oop для объекта. Как это проходит через это? У меня нет заполненной рекурсии, потому что я понятия не имею, как к этому подойти. Если я вызываю рекурсию для объекта, она переходит к следующему свойству объекта? Если так, то как? Разве вы не начали бы сначала все с самого начала? Я предполагаю, что моя логика c заключается в том, что for l oop НЕ продолжается с каждой вызванной рекурсии, потому что она выполняет функцию, которая запускает l oop с первого свойства

Ответы [ 3 ]

1 голос
/ 21 марта 2020

for..in циклы повторяются по свойствам , а не значениям - (var value in someObject) будет вводить в заблуждение и приводить к ошибкам.

Если у вас есть ссылка на значение объекта, проверьте, является ли это объектом или нет. Если это объект, вызовите рекурсивный objectRecursion и присвойте результат объекту result с тем же свойством. (Не return на данный момент, так как это завершит функцию)

Обратите внимание, что typeof является ключевым словом, а не функцией - не ставьте круглые скобки после него.

С этим связана проблема, связанная с тем, что null typeof тоже object, поэтому вам придется сравнивать и это.

var input2 = {1: 'a', 2: 'b', 3: 'c', foo: { prop: 2 }};

const objectRecursion = (someObject) => {
  const result = {};
  for (const [key, value] of Object.entries(someObject)) {
    result[key] = typeof value === 'object' && value !== null
      ? objectRecursion(value)
      : value;
  }
  return result;
};
console.log(objectRecursion(input2));

Для более гибкой функции, которая также обрабатывает и копирует массивы:

var input2 = {1: 'a', 2: 'b', 3: 'c', foo: { prop: 2, prop2: [3, 4, 5, { nested: 'nested' }] }};

const objectRecursion = (someItem) => {
  if (typeof someItem !== 'object' && someItem !== null) {
    return someItem;
  }
  if (Array.isArray(someItem)) {
    return someItem.map(objectRecursion);
  }
  const result = {};
  for (const [key, value] of Object.entries(someItem)) {
    result[key] = objectRecursion(value)
  }
  return result;
};
console.log(objectRecursion(input2));
0 голосов
/ 21 марта 2020

Это должно работать рекурсивно, используя apply

https://jsfiddle.net/cz1frnL8/

var o = {1: 'a', 2: 'b', 3: 'c', foo: { prop: 2, prop2: [3, 4, 5, { nested: 'nested' }] }};


function process(key,value) {
    console.log(key + " : "+value);
}

function traverse(o,func) {
    for (var i in o) {
        func.apply(this,[i,o[i]]);  
        if (o[i] !== null && typeof(o[i])=="object") {
             traverse(o[i],func);
        }
    }
}

traverse(o,process);
0 голосов
/ 21 марта 2020

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

Деревья являются отличным примером это. Предположим, у меня есть дерево объектов узлов со следующей структурой:

4 - 8 - 9
|   |
2   5 - 7
|
1

Как объект JS, он может выглядеть следующим образом.

{
  val: 4,
  left: {
    val: 2,
    left: {
      val: 1
    }
  },
  right: {
    val: 8,
    left: {
      val: 5,
      right: {
        val: 7
      }
    },
    right: {
      val: 9
    }
  }
}

Обратите внимание, как если бы я был посмотрите на объект, представляющий левый или правый узел из root, он структурирован так же, как его родитель? Каждый из них фактически является своим собственным деревом, но объединен в более крупное дерево (это я и имею в виду под фракталом).

Если вы хотите найти наибольшее значение в этом дереве, вы можете сделать это с помощью рекурсии итерировать по ветвям.

const getLargest = function (node) {
  return Math.max(node.val, getLargest(node.left), getLargest(node.right));
};

Тем не менее, вполне возможно использовать рекурсию для меньших и меньших наборов пар ключ-значение внутри объекта. Это может выглядеть примерно так:

const exampleObject = {
  a: 1,
  b: 2,
  c: 3
};

const recurse = function(obj) {
  const keys = Object.keys(obj);
  const firstKey = keys[0];
  console.log(obj[firstKey]); // Or whatever; do a thing with the first key-value pair.

  const smallerObj = Object.assign({}, obj); // Create a clone of the original; not necessary, but probably a good idea.
  delete smallerObj[firstKey]; // Remove the key that we've just used.
  recurse(smallerObj);
};

Это немного менее естественно в JS, но все еще вполне выполнимо. JavaScript ключи объекта не отсортированы, но вы можете добавить сортировку к const keys = Object.keys(obj), если хотите выполнить ключи в некотором определенном порядке c.

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