【问题标题】:recursive function for nested array objects returns undefined嵌套数组对象的递归函数返回未定义
【发布时间】:2021-01-23 17:26:48
【问题描述】:

我正在尝试在嵌套层次结构中查找/提取特定对象。 当找到实体时,我 console.log 它然后返回它。 日志是正确的对象,但函数仍然返回 undefined。

有什么解决办法吗?我已经尝试过使用 map、reduce 和经典的 for 循环,但仍然返回 undefined。

const hierarchy = {
  id: '1',
  title: 'root',
  children: [
    {
      id: '2',
      title: 'second ab',
      children: [
        {
          id:'999',
          title: 'nested child AB',
           children: [
          {
            id:'88888',
            title: 'very nested child AB'
          }
        ],
        }
      ],
    },
    {
      id: '3',
      title: 'third ab',
      children: [
        {
          id:'444',
          title: 'nested child AB',
           children: [
          {
            id:'5555',
            title: 'very nested child AB'
          }
        ],
        }
      ],
    }
  ]
}

const findEntityToAddInHierarchy = (entityArr, entityId) => {
     return entityArr.forEach(entity => {
       if(entity.id === entityId) {
         console.log('found and returning', entity)
         return entity;
       } else {
           return entity.children && findEntityToAddInHierarchy(entity.children, entityId)
       }
     })
  }


const result = findEntityToAddInHierarchy([hierarchy], '5555');

console.log('this returns undefined', result)

【问题讨论】:

  • 嗨!您可以在问题正文中使用标签指定语言;您还可以通过在代码块中指定语言来添加颜色语法,例如编写 ```javascript insert.code.here() ```

标签: javascript loops recursion undefined hierarchy


【解决方案1】:

正如 imvrain2 已经解释的那样,您的代码中存在forEach 的问题。该答案是解决此问题的一种方法。

但我相信我们可以更简单地写这个。这是一个返回数组中的 all 匹配项的版本。如果有多个具有相同 id 的值,它们都会出现。如果没有,它将是一个空数组。如果您确定三个始终是一个,则可以选择仅从列表中提取第一个结果(尽管我认为这可能是浪费。)

const matchById = (target) => (obj) => [
  ... (obj.id === target ? [obj] : []), 
  ... (obj .children || []) .flatMap (matchById (target))
]

const hierarchy = {id: '1', title: 'root', children: [{id: '2', title: 'second ab', children: [{id:'999', title: 'nested child AB', children: [{id:'88888', title: 'very nested child AB'}]}]}, {id: '3', title: 'third ab', children: [{id:'444', title: 'nested child AB', children: [{id:'5555', title: 'very nested child AB'}]}]}]}

console .log (matchById ('5555') (hierarchy))

我们返回一个以当前对象开头的数组(如果它具有正确的 id),然后简单地在其每个子对象上递归,展平为一个数组。

不过,只需多做一点工作,我们就可以使它更通用,我们使用谓词测试每个元素以确定我们是否要接受它,然后使用它来构建我们的自定义函数:

const getMatches = (pred) => (obj) => [
  ... (pred (obj) ? [obj] : []), 
  ... (obj .children || []) .flatMap (getMatches (pred))
]

const matchById = (target) =>
  getMatches (({id}) => id === target)

const hierarchy = {id: '1', title: 'root', children: [{id: '2', title: 'second ab', children: [{id:'999', title: 'nested child AB', children: [{id:'88888', title: 'very nested child AB'}]}]}, {id: '3', title: 'third ab', children: [{id:'444', title: 'nested child AB', children: [{id:'5555', title: 'very nested child AB'}]}]}]}

console .log (matchById ('5555') (hierarchy))

现在我们可以找到我们可以定义的任何谓词的所有匹配项。这是我会使用的版本。

【讨论】:

  • flatMap 是查找所有匹配项的不错选择。干得好
【解决方案2】:

我认为生成器特别适合搜索算法。我们可以从编写一个通用的preorder 遍历开始,它产生一个扁平的对象流。然后写searchById 是一个简单的for..of 构造-

function* preorder (t = {})
{ yield t
  if (t.children)
    for (const c of t.children)
      yield* preorder(c)
}

function searchById (t = {}, q = null)
{ for (const v of preorder(t))
    if (v.id == q)
      return v
  return false
}

const input =
  {id: '1', title: 'root', children: [{id: '2', title: 'second ab', children: [{id:'999', title: 'nested child AB', children: [{id:'88888', title: 'very nested child AB'}]}]}, {id: '3', title: 'third ab', children: [{id:'444', title: 'nested child AB', children: [{id:'5555', title: 'very nested child AB'}]}]}]}

const result = 
  searchById(input, 5555)
  
console.log(result)

{
  "id": "5555",
  "title": "very nested child AB"
}

如果没有找到结果,则返回false -

const result = 
  searchById(input, "Z")
  
console.log(result)
false

【讨论】:

    【解决方案3】:

    forEach 不返回任何内容,因此一种解决方案是设置一个变量。然后返回变量。

    const hierarchy = {
      id: '1',
      title: 'root',
      children: [
        {
          id: '2',
          title: 'second ab',
          children: [
            {
              id:'999',
              title: 'nested child AB',
               children: [
              {
                id:'88888',
                title: 'very nested child AB'
              }
            ],
            }
          ],
        },
        {
          id: '3',
          title: 'third ab',
          children: [
            {
              id:'444',
              title: 'nested child AB',
               children: [
              {
                id:'5555',
                title: 'very nested child AB'
              }
            ],
            }
          ],
        }
      ]
    }
    
    const findEntityToAddInHierarchy = (entityArr, entityId) => {
         _r = {};
         entityArr.forEach(entity => {
           if(entity.id === entityId) {
             console.log('found and returning', entity)
             _r = entity;
           } else {
               _r = entity.children && findEntityToAddInHierarchy(entity.children, entityId)
           }
         })
         return _r
      }
    
    
    const result = findEntityToAddInHierarchy([hierarchy], '5555');
    
    console.log('this returns undefined', result)

    【讨论】:

      猜你喜欢
      • 2012-09-26
      • 1970-01-01
      相关资源
      最近更新 更多