下面的代码告诉我们是否在多级嵌套对象中找到了值。
我知道使用递归可以很容易地实现这一点,我想知道它是如何迭代完成的?
Html::a(Html::encode($model->title),
['article/detail', 'id' => $model->id, 'title' => $model->title])
答案 0 :(得分:2)
非递归版本可能如下所示:
function deepSearch(obj, value) {
let queue = [obj],
found = false;
while (!found && queue.length) {
let o = queue.shift();
found = Object.keys(o).some(function (k) {
if (o[k] === value)
return true;
if (o[k] !== null && typeof o[k] === 'object')
queue.push(o[k]);
});
}
return found;
}
//
tree = {
a: {
b: 1,
c: {
d: 2
}
},
e: {
f: 3
}
};
console.log(deepSearch(tree, 3));
console.log(deepSearch(tree, 9));

我的想法是,不是通过递归调用立即处理子对象,而是将它放在队列中并保持循环,直到队列为空或我们找到我们正在寻找的内容。
此外,您的原始版本无法按预期工作,您需要.some
,而不是.forEach
。
答案 1 :(得分:0)
var data = {
prop1: 1,
prop2: {
prop21: true,
prop22: {
prop221: "prop221"
},
prop23: "prop23"
},
prop3: "prop3",
prop4: "prop4",
prop5: [{ prop511: true }, { prop512: false }, { prop513: true }, { prop514: true }],
prop6: [4, 5, 6],
prop7: [
[
{ prop7111: "prop7111" }
]
]
};
function TraverseObject(data) {
var currentContextObject = data;
var currentContextObjectProperties = Object.keys(data);
var contextStorage = []; //{contextObject: {}, contextObjectProperties: []}
while (currentContextObjectProperties.length !== 0 || contextStorage.length !== 0) {
var currentContextProperty = currentContextObjectProperties.shift();
if (currentContextProperty) {
if (!currentContextObject.hasOwnProperty(currentContextProperty)) {
break;
}
var currentContextPropertyValue = currentContextObject[currentContextProperty];
if (typeof currentContextPropertyValue === "object") {
contextStorage.push({
contextObject: currentContextObject,
contextObjectProperties: currentContextObjectProperties
});
currentContextObject = currentContextPropertyValue;
currentContextObjectProperties = Object.keys(currentContextObject);
continue;
}
console.log(`${currentContextProperty}--${currentContextPropertyValue}`);
}
if (currentContextObjectProperties.length === 0 && contextStorage.length !== 0) {
var popStorage = contextStorage.pop();
currentContextObject = popStorage.contextObject;
currentContextObjectProperties = popStorage.contextObjectProperties;
}
}
}
TraverseObject(data);
这将完成工作。 通过删除已经访问过的属性,可以稍微减少空间的复杂性。