迭代遍历嵌套对象中的所有节点(不使用递归)

时间:2017-07-31 12:28:56

标签: javascript loops object recursion iteration

下面的代码告诉我们是否在多级嵌套对象中找到了值。

我知道使用递归可以很容易地实现这一点,我想知道它是如何迭代完成的?

Html::a(Html::encode($model->title), 
        ['article/detail', 'id' => $model->id, 'title' => $model->title])

2 个答案:

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

这将完成工作。 通过删除已经访问过的属性,可以稍微减少空间的复杂性。