Рекурсировать вложенный объект в поисках свойства и добавить его в массив, если он есть - PullRequest
0 голосов
/ 31 октября 2019

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

Это мой текущий псевдокод.

  1. Проверьте, имеет ли obj свойство subProperty.

  2. Еслиу него его нет, верните false

  3. Если он есть, перейдите на один уровень глубиной (obj.subProperty) и проверьте, имеет ли оно свойство subProperty и т. д. ..

Я хочу сделать это recursively однако я не могу обдумать это. Может ли кто-нибудь помочь мне с функцией рекурсии, чтобы проверить на каждом уровне, если у него есть это свойство, и если да, нажмите true в массив

const obj = {
  level1: 'level 1',
  subProperty: {
    level2: 'level 2',
    subProperty: {
      level3: 'level 3'
    }
  }
}

Я пытаюсь изучить и понять recursion Помощь будетвысоко ценится.

Ответы [ 3 ]

1 голос
/ 31 октября 2019

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

function getLevels({ subProperty }) {
    if (subProperty === undefined) return [false];
    return [true, ...getLevels(subProperty)];
}

const
    object = { level1: 'level 1', subProperty: { level2: 'level 2', subProperty: { level3: 'level 3' } } },
    levels = getLevels(object);

console.log(levels);
0 голосов
/ 31 октября 2019

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

Так что вот вариант, который, я думаю, должен помочь: вместо возвратаfalse, мы могли бы вернуть первый вложенный объект без свойства subProperty. Таким образом, для вашего примера объекта это должно вернуть ссылку на вложенный {level3: 'level 3'} объект.

Поскольку наша структура данных явно рекурсивная, это хорошее место для использования рекурсивного решения. Вот одна из возможностей:

const levelWithoutSubProperty = function (obj) {
  if ('subProperty' in obj) {
    return levelWithoutSubProperty (obj .subProperty)
  }
  return obj;
}

const obj = {level1: 'level 1', subProperty: {level2: 'level 2', subProperty: {level3: 'level 3'}}}

console .log (
  levelWithoutSubProperty (obj)  //~> {level3: 'level 3'}
)

Вот как это работает:

levelWithoutSubProperty({level1: 'level 1', subProperty: {level2: 'level 2', subProperty: {level3: 'level 3'}}})
// `'subProperty' in obj` returns true, so call `levelWithoutSubProperty` with its subProperty:
    levelWithoutSubProperty({level2: 'level 2', subProperty: {level3: 'level 3'}})
    // `'subProperty' in obj` returns true, so call `levelWithoutSubProperty` with its subProperty:
        levelWithoutSubProperty({level3: 'level 3'})
        // `'subProperty' in obj` returns false so
        return {level3: 'level 3'}
    return {level3: 'level 3'}
return {level3: 'level 3'}

Прямая рекурсия (есть другие типы, но они не намного сложнее), включая функцию, вызывающую саму себяс данными, которые в некотором роде упрощены от своих собственных параметров. В какой-то момент ввод должен быть достаточно простым, чтобы вы могли вычислить результат без другого рекурсивного вызова. Это называется base case , и важно, чтобы в каждой рекурсивной функции был хотя бы один. В противном случае функция будет продолжать вызывать себя бесконечно.

Здесь наш единственный базовый случай - когда obj не имеет свойства subProperty, то есть когда 'subproperty' in obj возвращает false. В этом случае мы просто возвращаем предоставленный параметр.

Рекурсивная функция также будет иметь один или несколько рекурсивных вызовов. Здесь у нас есть только один. Мы снова вызываем нашу функцию со свойством subProperty нашего объекта: return levelWithoutSubProperty (obj .subProperty)


Есть и другие вещи, которые мы могли бы сделать с этой функцией, чтобы сделать ее более устойчивой. Вероятно, мы должны проверить, что obj на самом деле является объектом перед использованием 'subProperty' in obj. И я предпочитаю использовать выражения, а не такие выражения, как if. Поэтому я, вероятно, сам написал бы это так:

const levelWithoutSubProperty = (obj) =>
  typeof obj == 'object' && 'subProperty' in obj
    ? levelWithoutSubProperty (obj .subProperty)
    : obj

Мы могли бы захотеть сделать имя свойства для тестирования динамическим, добавив его в качестве параметра:

const deepest = (propName, obj) => 
  typeof obj == 'object' && propName in obj
    ? deepest (propName, obj [propName])
    : obj

и вызвав егокак deepest ('subProperty', obj).

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

Вот что такое рекурсия.

0 голосов
/ 31 октября 2019

hasOwnProperty может проверить, есть ли у объекта свойство, указанное в качестве аргумента. Вы можете создать цикл while для продолжения до тех пор, пока не будет найдено свойство, у которого нет подвойства. Вот короткий скрипт, демонстрирующий функцию для этого. Он вернет массив с true для всех случаев, когда он мог продолжаться, и false в последний раз.

const obj = {
  level1: 'level 1',
  subProperty: {
    level2: 'level 2',
    subProperty: {
      level3: 'level 3'
    }
  }
}

function getSubPropertyRecursive(obj, subProperty) {
  propertyArray = [];
  currentObj = obj
  while (currentObj.hasOwnProperty(subProperty)){
    currentObj = currentObj[subProperty];
    propertyArray.push(true);
  }
  propertyArray.push(false);
  return propertyArray;
}
   
console.log(getSubPropertyRecursive(obj, "subProperty"));
...