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