JavaScript:返回递归的结果

时间:2014-12-31 15:12:48

标签: javascript function recursion

我编写了以下函数来遍历JSON结构数据,以找到提供的targetField和路径pathArr的值,但我正在努力从递归返回结果,因为值对于targetField可能不存在。

此函数使用名为 result 的全局变量来返回targetField的值,但是这可以转移到findValue()的下一次调用,它可能找不到值但是显示最后一个电话result。所以我想知道在不使用全局变量result的情况下解决此问题的最佳方法是什么。

如果调用findValue()找不到targetField的值,只需返回 null作为结果

pathArr 类似["first_level", "second_level", "third_level"];

var result = null;
function findValue(jsonData, pathArr, targetField) {

if (pathArr.length == 0) {
    result = targetField in jsonData ? jsonData[targetField] : result;
    return result;
} else {

    var curNode = pathArr.shift();

    if (curNode in jsonData) {
        jsonData = jsonData[curNode];
    }

    if (Array.isArray(jsonData)) {
        jsonData.forEach(function(thisData) {
            findValue(thisData, pathArr, targetField);
        });
    } else {
        findValue(jsonData, pathArr, targetField);
    }
}   

return result;
}

修改 感谢所有回复的人。

使用unobf改进的代码,我使用此testData进行测试,但似乎只返回最后一个匹配:

var testData = {
"num_found" : 3,
"category" : "social",

"groups": [ 
{"group" : {
    "source" : [{"id" : "testID1", "num": 10, "field": "sociaology", "sub-subject" : "socialeconomy"}, 
                {"id" : "testID2", "num": 20, "field": "mathematics", "sub-subject": ""}, 
                {"id" : "testID3", "num": 7, "field": "biology", "sub-subject" : ""}
                ],
    "identifier" : "shelf-01-E-XW1"
}},
{"group" : {
    "source" : [{"id" : "testID4", "num": 50, "field": "sociaology2", "sub-subject" : ""}, 
                {"id" : "testID5", "num": 44, "field": "mathematics2", "sub-subject": ""}, 
                {"id" : "testID6", "num": 75, "field": "biology2", "sub-subject" : "european studies2"}
                ],
    "identifier" : "shelf-02-W-EW3"
}},

{"group" : {
    "source" : [{"id" : "testID7", "num": 59, "field": "sociaology3", "sub-subject" : "socialeconomy3"}, 
                {"id" : "testID8", "num": 47, "field": "mathematics3", "sub-subject": ""}, 
                {"id" : "testID9", "num": 76, "field": "biology3", "sub-subject" : "european studies3"}
                ],
    "identifier" : "shelf-03-W-GW5"
}}
]
};

我发现我必须改变这行代码

return {value : result};

return result;

测试

for (var i = 0; i < testData.groups.length; i++) {
    var value = findValue(testData.groups[i], ["group", "source"], "sub-subject");
    console.log("found value: " + value);
}

2 个答案:

答案 0 :(得分:1)

从根本上说,函数中的所有路径都必须返回一个值。目前,还有一条路径不是forEach所采用的路径:

jsonData.forEach(function(thisData) {
    findValue(thisData, pathArr, targetField);
});

在那里,您可能需要some(这样您可以在找到它时停止)和一个可以设置为找到值的变量,例如:

var retval;

jsonData.some(function(thisData) {
    retVal = findValue(thisData, pathArr, targetField);
    return !!retVal; // Stops the `some` loop, doesn't exit `findValue`
});
if (retVal) {
    return retVal;
}

附注:您不想在功能之外声明result,没有必要。该功能可以完全独立。这是一个自包含的版本,例如:

function findValue(jsonData, pathArr, targetField) {
    var result = null;

    if (pathArr.length == 0) {
        result = targetField in jsonData ? jsonData[targetField] : null;
    } else {

        var curNode = pathArr.shift();

        if (curNode in jsonData) {
            jsonData = jsonData[curNode];
        }

        if (Array.isArray(jsonData)) {
            jsonData.some(function(thisData) {
                result = findValue(thisData, pathArr, targetField);
                return !!result; // Stops the `some` loop, doesn't exit `findValue`
            });
        } else {
            result = findValue(jsonData, pathArr, targetField);
        }
    }

    return result;
}

注意:我没有对代码进行全面审核,只看了一下返回值。

答案 1 :(得分:1)

以下是包含一些测试数据的解决方案

function findValue(jsonData, pathArr, targetField) {
    var result = null;

    if (pathArr.length == 0 && jsonData.hasOwnProperty(targetField)) {
        result = targetField in jsonData ? jsonData[targetField] : result;
        return { value : result};
    } else {
        jsonData = jsonData[pathArr.shift()]
        if (Array.isArray(jsonData)) {
            jsonData.forEach(function(thisData) {
                result = findValue(thisData, pathArr, targetField);
            });
        } else if (typeof jsonData !== 'undefined') {
            return findValue(jsonData, pathArr, targetField);
        }
    }   
    return result;
}

testData = [{
    hello : 'hello',
    pathArr: []
}, {
    child : {
        hello : false
    },
    pathArr: ['child']
}, {
    child : {
        hello : null
    },
    pathArr: ['child']
}, {
    child: {
        child: {
            hell: 'hell'
        }
    },
    pathArr: ['child', 'child']
}];



testData.forEach(function (json) {
    console.log(findValue(json, json.pathArr, 'hello'));
});