如何在递归for循环函数中返回值?

时间:2019-01-08 04:18:10

标签: javascript algorithm for-loop recursion search

这是代码。

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值与location参数匹配的对象块。
我可以使控制台日志正常工作。但是我无法获得返回的数据。 (我已经尝试过递归地返回该函数,但仍然无法正常工作。)
我做错了什么?

2 个答案:

答案 0 :(得分: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)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.core.min.js"></script>

但是,如果您将数组迭代和对象测试分开,则逻辑可能一目了然,而无需大型库即可完成此工作:

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

答案 1 :(得分:1)

一个很好的学习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。谢谢,功能风格。