递归嵌套对象以查找属性,并将其添加到数组中(如果存在)

时间:2019-10-30 22:09:05

标签: javascript recursion

我试图遍历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 个答案:

答案 0 :(得分:1)

您可以返回一个带有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);

答案 1 :(得分:0)

我认为所提出的问题并不能真正帮助您学习更多有关递归的知识。根据定义,该函数将始终返回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'}

直接递归(还有其他类型,但并不复杂)涉及到一个函数,该函数使用从其自身参数以某种方式简化的数据来调用自身。在某些时候,输入必须足够简单,以使您无需再次进行递归调用即可计算结果。这称为基本情况,每个递归函数至少要有一个很重要。否则,该函数将继续无限期地调用自身。

在这里,我们唯一的基本情况是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)这样称呼它。

但是,基本内容没有任何变化。我们有一个或多个直接返回值的基本案例,以及一个或多个递归调用,这些递归调用使用一些简化的数据再次调用我们的函数。

这就是递归的全部内容。

答案 2 :(得分:-1)

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"));