我想在嵌套的JSON对象中搜索字符串。如果在对象中找到字符串,我需要返回该对象。
我正在使用递归函数来实现这一目标。问题是,函数递归到最后并且没有返回找到的对象。
Please see the entire code in jsfiddle
function search(obj, name) {
console.log(obj["name"], ",", name, obj["name"] == name);
if (obj["name"] == name) {
return obj; //NOT RETURNING HERE
}
if (obj.children || obj._children) {
var ch = obj.children || obj._children;
//console.log(ch);
ch.forEach(function(val) {
search(val, name)
});
}
return -1;
}
search(myJson, "VM10-Proc4")
我不确定会出现什么问题。
答案 0 :(得分:8)
当找到匹配的子项时,您需要停止循环子项。
function search(obj, name) {
console.log(obj.name, ",", name, obj.name == name);
if (obj.name == name) {
return obj;
}
if (obj.children || obj._children) {
var ch = obj.children || obj._children;
for (var i = 0; i < ch.length; i++) {
var found = search(ch[i], name);
if (found) {
return found;
}
}
}
return false;
}
答案 1 :(得分:4)
正确的返回值在递归函数调用链中丢失。找到正确的值后,所做的任何其他搜索都将从该点返回不正确的值。
有几种方法可以解决这个问题:
<强> 1。取消搜索
当找到正确的值时,立即将它一直返回到递归堆栈,而不再搜索当前数组或嵌套数组。换句话说,取消搜索的其余部分。
@ Barmer的答案就是一个例子。他的代码的关键部分是使用for
循环而不是each
方法来遍历数组,因为中断for
循环要容易得多。
<强> 2。将值存储在安全的地方
找到正确的值后,将其存储在安全的地方,允许其余的搜索继续,并在初始函数调用完成后访问该值。最简单的方法是将正确的值存储在全局变量中,尽管这不是一个好的做法,因为它违反了函数的封装。
在两者之间进行选择
用外行人的话说,这个功能的预期逻辑可以总结如下:当你找到你想要的东西时,停下来,让我立刻知道它是什么。继续搜索的唯一原因是需要找到多个数据。我假设这不是这种情况。
在这两种方法中,#2是一种快速解决方法,应该可以正常工作,但会进一步混淆任何试图理解该功能的预期逻辑的人。如果只搜索已经找到的单个数据,为什么搜索仍在继续?
#1是函数的重构,因此它的行为与预期的逻辑更加一致,这将使函数更容易理解。该功能在找到所需内容时停止搜索。
答案 2 :(得分:1)
由于您正在递归,因此返回可能嵌套得太深,无法获得有意义的结果。相反,您可以尝试传递额外的参数来收集结果。
function search(obj, name, ret) {
console.log(obj["name"], ",", name, obj["name"] == name);
if (obj["name"] == name) {
ret.push(obj);
return
}
if (obj.children || obj._children) {
var ch = obj.children || obj._children;
ch.forEach(function(val) {
search(val, name, ret);
});
}
}
var result = [];
search(myJson, "VM10-Proc4", result)
答案 3 :(得分:0)
我知道这是一篇旧帖子,但我可以看到2个问题:
1)递归调用不会将结果返回到调用堆栈,即
search(val, name)
应该是
return search(val, name)
2)看起来你正在使用array.forEach()。文档说明:
除了抛出异常之外,没有办法停止或中断forEach()循环。如果您需要这样的行为,forEach()方法是错误的工具。请改用普通循环。如果要测试谓词的数组元素并需要布尔返回值,则可以使用every()或some()。如果可用,新方法find()或findIndex()也可用于在真正的谓词上提前终止。
这意味着,实际上,当您找到要查找的结果时,您希望将其发送回调用堆栈。使用array.forEach将继续以递归方式查看层次结构并返回所有值,而不仅仅是您感兴趣的值。因此,最后返回的值可能是您不期望的值,例如undefined!因此,使用不同的迭代方法,即
for (var i = 0; i < ch.length; i++) {
var val = ch[i];
return search(val, name, ret);
}
接受的答案是勺子喂你这个答案的一部分,但没有解释原因。因此这个答案