【问题标题】:How to return value in a recursively for loop function?如何在递归for循环函数中返回值?
【发布时间】:2019-06-02 18:05:19
【问题描述】:

这是代码。

var temp = [
    { 
    slugs: ['men'], 
    children: [
      { slugs: ['men', 'tops'], children: [
        { slugs: ['men', 'tops', 'shirts'] },
        { slugs: ['men', 'tops', 'swe'] }
      ] },
      {
        slugs: ['men', 'bottoms'], children: [
          { slugs: ['men', 'bottoms', 'pants'] },
          { slugs: ['men', 'bottoms', 'under'] }
        ]
      }
    ] 
  },
  {
    slugs: ['women'], 
    children: [
      { slugs: ['women', 'tops'], children: [
        { slugs: ['women', 'tops', 'shirts'] },
        { slugs: ['women', 'tops', 'swe'] }
      ] },
      {
        slugs: ['women', 'bottoms'], children: [
          { slugs: ['women', 'bottoms', 'pants'] },
          { slugs: ['women', 'bottoms', 'under'] }
        ]
      }
    ] 
  }
]

function matchTreeObj (tree, location) {
  if (_.isArray(tree) && tree.length > 0) {
    for(let i=0;i<tree.length;i++){
        matchTreeObj(tree[i], location)
    }
  }
  if (tree.slugs && (tree.slugs.join('/') === location)) {
    console.log(tree)
    return tree
  } else if (tree.children && tree.children.length > 0) {
    matchTreeObj(tree.children, location)
  }
}
const aaa = matchTreeObj(temp, 'men/tops')

console.log('from log', aaa)

它正在使用 lodash,fiddle 在这里。
该代码基本上输出其slugs 值与位置参数匹配的对象块。
我可以让控制台日志正常工作。但我无法获得返回的数据。 (我已经尝试返回递归使用它的函数,但仍然无法正常工作。)
我做错了什么?

【问题讨论】:

    标签: javascript algorithm for-loop recursion search


    【解决方案1】:

    for 循环中迭代数组时,检查调用 matchTreeObj 的输出 - 如果是真的,则返回:

    for(let i=0;i<tree.length;i++){
      const result = matchTreeObj(tree[i], location)
      if (result) return result;
    }
    

    同样返回下层else if中的递归调用:

    } else if (tree.children && tree.children.length > 0) {
      return matchTreeObj(tree.children, location)
    }
    

    var temp = [
    	{ 
      	slugs: ['men'], 
        children: [
          { slugs: ['men', 'tops'], children: [
            { slugs: ['men', 'tops', 'shirts'] },
            { slugs: ['men', 'tops', 'swe'] }
          ] },
          {
            slugs: ['men', 'bottoms'], children: [
              { slugs: ['men', 'bottoms', 'pants'] },
              { slugs: ['men', 'bottoms', 'under'] }
            ]
          }
        ] 
      },
      {
      	slugs: ['women'], 
        children: [
          { slugs: ['women', 'tops'], children: [
            { slugs: ['women', 'tops', 'shirts'] },
            { slugs: ['women', 'tops', 'swe'] }
          ] },
          {
            slugs: ['women', 'bottoms'], children: [
              { slugs: ['women', 'bottoms', 'pants'] },
              { slugs: ['women', 'bottoms', 'under'] }
            ]
          }
        ] 
      }
    ]
    
    function matchTreeObj (tree, location) {
      if (_.isArray(tree) && tree.length > 0) {
        for(let i=0;i<tree.length;i++){
        	const result = matchTreeObj(tree[i], location)
          if (result) return result;
        }
      }
      if (tree.slugs && (tree.slugs.join('/') === location)) {
        return tree
        } else if (tree.children && tree.children.length > 0) {
          return matchTreeObj(tree.children, location)
        }
    }
    const aaa = matchTreeObj(temp, 'men/tops')
    
    console.log('from log', aaa)
    &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.core.min.js"&gt;&lt;/script&gt;

    如果你把数组迭代和对象测试分开,逻辑可能会更容易一目了然,而且不需要一个大的库来完成这个:

    var temp=[{slugs:['men'],children:[{slugs:['men','tops'],children:[{slugs:['men','tops','shirts']},{slugs:['men','tops','swe']}]},{slugs:['men','bottoms'],children:[{slugs:['men','bottoms','pants']},{slugs:['men','bottoms','under']}]}]},{slugs:['women'],children:[{slugs:['women','tops'],children:[{slugs:['women','tops','shirts']},{slugs:['women','tops','swe']}]},{slugs:['women','bottoms'],children:[{slugs:['women','bottoms','pants']},{slugs:['women','bottoms','under']}]}]}];
    
    function matchArr(arr, location) {
      for (const item of arr) {
        const result = matchItem(item, location);
        if (result) return result;
      }
    }
    function matchItem(item, location) {
      if (item.slugs.join('/') === location) {
        return item;
      } else if (item.children) {
        return matchArr(item.children, location);
      }
    }
    const output = matchArr(temp, 'men/tops')
    console.log(output);

    【讨论】:

      【解决方案2】:

      了解mutual recursion 的好机会——在数学和计算机科学中,相互递归是一种递归形式,其中两个数学或计算对象(例如函数或数据类型)是相互定义的。相互递归在函数式编程和某些问题领域中非常常见,例如递归下降解析器,其中数据类型自然是相互递归的——

      type node =
        { slugs : string array
        , children : node array
        }
      

      每个节点都有一个 children 属性,它是一个节点数组,每个节点都有一个包含更多节点的 children 属性。至此,递归数据结构和应用相互递归技术的好时机就完成了。

      下面,match 调用 match1,而后者又调用 match。这两个函数都是使用纯表达式编写的。不需要for 循环,因为for 是一个语句,依赖于副作用,并且以命令式风格使用。函数式风格避免了副作用,因此有利于使用递归来代替 for 循环 –

      const None =
        Symbol ()
      
      const EmptyNode =
        { slugs: []
        , children: []
        }
      
      const match1 = (s = "", node = EmptyNode) =>
        node.slugs .join ('/') === s
          ? node
          : match (s, node.children)
      
      const match = (s = "", [ node = None, ...rest ] = []) =>
        node === None
          ? undefined
          : match1 (s, node) || match (s, rest)
      
      console .log
        ( match ("men/tops", data)       // { slugs: [ men, tops ], ... }
        , match ("women/bottoms", data)  // { slugs: [ women, bottoms ], ... }
        , match ("cat/dog", data)        // undefined
        )
      

      一个小的调整允许我们收集所有结果,而不是在第一个匹配后停止 -

      const EmptyNode =
        { slugs: []
        , children: []
        }
      
      const match1 = (s = "", node = EmptyNode) =>
        node.slugs .join ('/') === s
          ? [ node, ...match (s, node.children) ]
          : match (s, node.children)
      
      const match = (s = "", nodes = []) =>
        nodes .flatMap (x => match1 (s, x))
      
      console .log
        ( match ("men/tops", data) // [ ... all matches ... ]
        , match ("cat/dog", data)  // []
        )
      

      嘿看,我们返回了一个值,甚至没有使用return。谢谢,实用风格。

      【讨论】:

        猜你喜欢
        • 2013-01-31
        • 2022-06-15
        • 2018-01-23
        • 2016-03-23
        • 2020-06-18
        • 1970-01-01
        • 1970-01-01
        • 2014-10-02
        • 2017-05-09
        相关资源
        最近更新 更多