如何从同一级别(对象而非数组)的不同记录中提取多个javascript值

如何从同一级别(对象而非数组)的不同记录中提取多个javascript值,javascript,Javascript,我可以得到我想要的三个值 > surfing.surfreport[0].monday["1pm"].tide 5 > surfing.surfreport[0].monday["2pm"].tide -1 > surfing.surfreport[0].monday["3pm"].tide -1 > 但是我怎样才能用一个表达式得到这三个值呢 我尝试了不同的选择器和映射操作,比如 > surfing.surfreport[0].monday.map(time =

我可以得到我想要的三个值

> surfing.surfreport[0].monday["1pm"].tide
5
> surfing.surfreport[0].monday["2pm"].tide
-1
> surfing.surfreport[0].monday["3pm"].tide
-1
> 
但是我怎样才能用一个表达式得到这三个值呢

我尝试了不同的选择器和映射操作,比如

> surfing.surfreport[0].monday.map(time => time.tide)
但是我有

Uncaught TypeError: surfing.surfreport[0].monday.map is not a function
任何一个单独的值,但我如何才能得到,比如说,所有的3个潮汐值。要么通过我的json查询,要么通过js方法

surfing = 
{    "surfreport": [
        {
            "beach": "Santa Cruz",
            "monday": {
                "1pm": {
                    "tide": 5,
                    "wind": 15,
                    "watertemp": 80,
                    "surfheight": 5,
                    "recommendation": "Go surfing!"
                },
                "2pm": {
                    "tide": -1,
                    "wind": 1,
                    "watertemp": 50,
                    "surfheight": 3,
                    "recommendation": "Surfing conditions are okay, not great."
                },
                "3pm": {
                    "tide": -1,
                    "wind": 10,
                    "watertemp": 65,
                    "surfheight": 1,
                    "recommendation": "Not a good day for surfing."
                }
            }
        }
    ]
}

可以在属性数组上映射:

[“1pm”、“2pm”、“3pm”].map(v=>surfing.surfreeport[0]。星期一[v]。潮汐);

您可以在属性数组上映射:

[“1pm”、“2pm”、“3pm”].map(v=>surfing.surfreeport[0]。星期一[v]。潮汐);

此语句将创建一个对象数组,每个对象包含
tide
wind
watertemp

let reports = Object.values(surfing.surfreport[0].monday);
// [ {tide: 5, wind: 15, ...}, {tide: -1, wind: 1, ...}, ... ]
然后,要创建仅包含潮汐值的数组,请执行以下操作:

let tides = reports.map(obj => obj.tide);
// [ 5, -1, -1 ]
用一句话来说:

let tides = Object.values(surfing.surfreport[0].monday)
                  .map(obj => obj.tide);

此语句将创建一个对象数组,每个对象包含
tide
wind
watertemp

let reports = Object.values(surfing.surfreport[0].monday);
// [ {tide: 5, wind: 15, ...}, {tide: -1, wind: 1, ...}, ... ]
然后,要创建仅包含潮汐值的数组,请执行以下操作:

let tides = reports.map(obj => obj.tide);
// [ 5, -1, -1 ]
用一句话来说:

let tides = Object.values(surfing.surfreport[0].monday)
                  .map(obj => obj.tide);

这些答案都很好,并且针对您的用例,但是没有一个能够解决标题问题

如果您不知道中间键名称(如
surfreeport
monday
等),该怎么办

如果您只知道要提取的级别,该怎么办

我写了一个函数来实现这一点

(function() {
    let stringified = JSON.stringify(surfing); // your JSON here (in place of surfing)
    let depthTarget = 5; // your target depth level

    let depthCounter = 0;
    let openBracket = /(?<!(\}|\{|\]|\[).*)(\{|\[)/;
    let closedBracket = /(?<!(\}|\{|\]|\[).*)(\}|\])/;
    let openBracketPosition = stringified.search(/(?<!(\}|\{|\]|\[).*)(\{|\[)/);
    let closedBracketPosition = stringified.search(/(?<!(\}|\{|\]|\[).*)(\}|\])/);
    let ourString;
    let done = false;

    function depthSearch() {
        // If an open curly bracket is followed by another open curly bracket,
        if (openBracketPosition !== -1 && stringified.substring(openBracketPosition + 1).search(openBracket) !== -1) {
            depthCounter += 1;
            depthTargetCheck(openBracketPosition, stringified.substring(openBracketPosition + 1).search(openBracket));
        }
        // If an open curly bracket is followed by a closed curly bracket,
        if (openBracketPosition !== -1 && stringified.substring(openBracketPosition + 1).search(closedBracket) !== -1) {
            depthCounter += 1;
            depthTargetCheck(openBracketPosition, stringified.substring(openBracketPosition + 1).search(closedBracket));
        }
        // If a closed curly bracket is followed by another closed curly bracket,
        if (closedBracketPosition !== -1 && stringified.substring(closedBracketPosition + 1).search(closedBracket) !== -1) {
            depthCounter -= 1;
            depthTargetCheck(closedBracketPosition, stringified.substring(closedBracketPosition + 1).search(closedBracket));
        }
        // If a closed curly bracket is followed by an open curly bracket,
        if (closedBracketPosition !== -1 && stringified.substring(closedBracketPosition + 1).search(openBracket) !== -1) {
            depthCounter -= 1;
            depthTargetCheck(closedBracketPosition, stringified.substring(closedBracketPosition + 1).search(openBracket));
        }
        // If we're at the end, i.e., if a closed curly bracket is not followed by any other curly brackets,
        if (closedBracketPosition !== -1 && stringified.substring(closedBracketPosition + 1).search(/(\{|\}|\]|\[)/) === -1) {
            // stop.
            done = true;
        }        
    }

    function depthTargetCheck(firstBracketPosition, secondBracketPosition) {
        // Check if we're at the target level. If we are,
        if (depthCounter === depthTarget) {
            ourString = stringified.substring(firstBracketPosition, secondBracketPosition + 2);
            // If the string is just closed brackets,
            if (ourString.search(/^(\}|\])*$/) !== -1) {
                // return nothing (but don't leave the function).
            } else {
                // If the string begins with a square bracket, i.e., if we're in an array,
                if (ourString.search(/^\[/) !== -1) {
                    // Check if the string ends in an open curly bracket. If it does,
                    if (ourString.search(/\{$/) !== -1) {
                        // replace the ending with a dummy 'object' string, and close off the array.
                        ourString = ourString.replace(/\{$/, '"[object]"]');
                    }
                // If the string ends in a square bracket, i.e., if we're in an array,
                } else if (ourString.search(/\]$/) !== -1) {
                    // Check if the string begins with an open curly bracket. If it does,
                    if (ourString.search(/^\},/) !== -1) {
                        // replace it with an open square bracket.
                        ourString = ourString.replace(/^\},/, '[');
                    }
                } else {
                    // If the last character isn't a closed curly bracket, i.e., if the value is an object or array,
                    if (ourString.charAt(ourString.length - 1) !== '}') {
                        // if the last character is just an open curly bracket,
                        if (ourString.search(/":\{$/) !== -1) {
                            // replace the ending with a dummy 'object' string and close off the JSON.
                            ourString = ourString.replace(/":\{$/, '":"[object]"}');
                        }
                        // if the last character has an open square bracket before it,
                        if (ourString.search(/":(\{|\[)+$/) !== -1) {
                            // replace the ending with a dummy 'array' string and close off the JSON.
                            ourString = ourString.replace(/":(\{|\[)+$/, '":"[array]"}');
                        }
                    }
                    // If the string begins with '},' or '],', i.e., it's not the first key at this level,
                    if (ourString.search(/^(\}|\]),/) !== -1) {
                        // convert it to '{'.
                        ourString = ourString.replace(/^(\}|\]),/, '{');
                    }
                }
                // Fetch the values of 'tide' at the target level.
                console.log(JSON.parse(ourString).tide); // your target key here (if applicable)
                // Or, alternatively, fetch all keys and values at the target level.
                //console.log(JSON.parse(ourString));
            }
        }
        // Continue searching beyond the closed bracket.
        stringified = stringified.substring(secondBracketPosition + 1);
        // Set the new first bracket positions to the new test string.
        openBracketPosition = stringified.search(/(?<!(\}|\{|\]|\[).*)(\{|\[)/);
        closedBracketPosition = stringified.search(/(?<!(\}|\{|\]|\[).*)(\}|\])/);
        depthSearch();
    }
    if (done) {
        return;
    }
    depthSearch();
})();
如果从最终的
控制台.log
中删除
.tide
,它将返回深度级别5的所有键及其值:

{tide: 5, wind: 15, watertemp: 80, surfheight: 5, recommendation: "Go surfing!"}
{tide: -1, wind: 1, watertemp: 50, surfheight: 3, recommendation: "Surfing conditions are okay, not great."}
{tide: -1, wind: 10, watertemp: 65, surfheight: 1, recommendation: "Not a good day for surfing."}
如果随后将depthTarget降低到4,它将返回

{1pm: "[object]"}
{2pm: "[object]"}
{3pm: "[object]"}
深度目标为3将导致

{beach: "Santa Cruz", monday: "[object]"}
["[object]"]
{surfreport: "[array]"}
而2导致

{beach: "Santa Cruz", monday: "[object]"}
["[object]"]
{surfreport: "[array]"}
1导致

{beach: "Santa Cruz", monday: "[object]"}
["[object]"]
{surfreport: "[array]"}

这并不完美。如果对象中的字符串中有方括号或花括号,或者值不能为空(基本上,只有当它是函数或
未定义时,它才起作用)。也许有人(或我)会过来修复该功能。

这些答案都很好,都针对您的用例,但都没有解决标题问题

如果您不知道中间键名称(如
surfreeport
monday
等),该怎么办

如果您只知道要提取的级别,该怎么办

我写了一个函数来实现这一点

(function() {
    let stringified = JSON.stringify(surfing); // your JSON here (in place of surfing)
    let depthTarget = 5; // your target depth level

    let depthCounter = 0;
    let openBracket = /(?<!(\}|\{|\]|\[).*)(\{|\[)/;
    let closedBracket = /(?<!(\}|\{|\]|\[).*)(\}|\])/;
    let openBracketPosition = stringified.search(/(?<!(\}|\{|\]|\[).*)(\{|\[)/);
    let closedBracketPosition = stringified.search(/(?<!(\}|\{|\]|\[).*)(\}|\])/);
    let ourString;
    let done = false;

    function depthSearch() {
        // If an open curly bracket is followed by another open curly bracket,
        if (openBracketPosition !== -1 && stringified.substring(openBracketPosition + 1).search(openBracket) !== -1) {
            depthCounter += 1;
            depthTargetCheck(openBracketPosition, stringified.substring(openBracketPosition + 1).search(openBracket));
        }
        // If an open curly bracket is followed by a closed curly bracket,
        if (openBracketPosition !== -1 && stringified.substring(openBracketPosition + 1).search(closedBracket) !== -1) {
            depthCounter += 1;
            depthTargetCheck(openBracketPosition, stringified.substring(openBracketPosition + 1).search(closedBracket));
        }
        // If a closed curly bracket is followed by another closed curly bracket,
        if (closedBracketPosition !== -1 && stringified.substring(closedBracketPosition + 1).search(closedBracket) !== -1) {
            depthCounter -= 1;
            depthTargetCheck(closedBracketPosition, stringified.substring(closedBracketPosition + 1).search(closedBracket));
        }
        // If a closed curly bracket is followed by an open curly bracket,
        if (closedBracketPosition !== -1 && stringified.substring(closedBracketPosition + 1).search(openBracket) !== -1) {
            depthCounter -= 1;
            depthTargetCheck(closedBracketPosition, stringified.substring(closedBracketPosition + 1).search(openBracket));
        }
        // If we're at the end, i.e., if a closed curly bracket is not followed by any other curly brackets,
        if (closedBracketPosition !== -1 && stringified.substring(closedBracketPosition + 1).search(/(\{|\}|\]|\[)/) === -1) {
            // stop.
            done = true;
        }        
    }

    function depthTargetCheck(firstBracketPosition, secondBracketPosition) {
        // Check if we're at the target level. If we are,
        if (depthCounter === depthTarget) {
            ourString = stringified.substring(firstBracketPosition, secondBracketPosition + 2);
            // If the string is just closed brackets,
            if (ourString.search(/^(\}|\])*$/) !== -1) {
                // return nothing (but don't leave the function).
            } else {
                // If the string begins with a square bracket, i.e., if we're in an array,
                if (ourString.search(/^\[/) !== -1) {
                    // Check if the string ends in an open curly bracket. If it does,
                    if (ourString.search(/\{$/) !== -1) {
                        // replace the ending with a dummy 'object' string, and close off the array.
                        ourString = ourString.replace(/\{$/, '"[object]"]');
                    }
                // If the string ends in a square bracket, i.e., if we're in an array,
                } else if (ourString.search(/\]$/) !== -1) {
                    // Check if the string begins with an open curly bracket. If it does,
                    if (ourString.search(/^\},/) !== -1) {
                        // replace it with an open square bracket.
                        ourString = ourString.replace(/^\},/, '[');
                    }
                } else {
                    // If the last character isn't a closed curly bracket, i.e., if the value is an object or array,
                    if (ourString.charAt(ourString.length - 1) !== '}') {
                        // if the last character is just an open curly bracket,
                        if (ourString.search(/":\{$/) !== -1) {
                            // replace the ending with a dummy 'object' string and close off the JSON.
                            ourString = ourString.replace(/":\{$/, '":"[object]"}');
                        }
                        // if the last character has an open square bracket before it,
                        if (ourString.search(/":(\{|\[)+$/) !== -1) {
                            // replace the ending with a dummy 'array' string and close off the JSON.
                            ourString = ourString.replace(/":(\{|\[)+$/, '":"[array]"}');
                        }
                    }
                    // If the string begins with '},' or '],', i.e., it's not the first key at this level,
                    if (ourString.search(/^(\}|\]),/) !== -1) {
                        // convert it to '{'.
                        ourString = ourString.replace(/^(\}|\]),/, '{');
                    }
                }
                // Fetch the values of 'tide' at the target level.
                console.log(JSON.parse(ourString).tide); // your target key here (if applicable)
                // Or, alternatively, fetch all keys and values at the target level.
                //console.log(JSON.parse(ourString));
            }
        }
        // Continue searching beyond the closed bracket.
        stringified = stringified.substring(secondBracketPosition + 1);
        // Set the new first bracket positions to the new test string.
        openBracketPosition = stringified.search(/(?<!(\}|\{|\]|\[).*)(\{|\[)/);
        closedBracketPosition = stringified.search(/(?<!(\}|\{|\]|\[).*)(\}|\])/);
        depthSearch();
    }
    if (done) {
        return;
    }
    depthSearch();
})();
如果从最终的
控制台.log
中删除
.tide
,它将返回深度级别5的所有键及其值:

{tide: 5, wind: 15, watertemp: 80, surfheight: 5, recommendation: "Go surfing!"}
{tide: -1, wind: 1, watertemp: 50, surfheight: 3, recommendation: "Surfing conditions are okay, not great."}
{tide: -1, wind: 10, watertemp: 65, surfheight: 1, recommendation: "Not a good day for surfing."}
如果随后将depthTarget降低到4,它将返回

{1pm: "[object]"}
{2pm: "[object]"}
{3pm: "[object]"}
深度目标为3将导致

{beach: "Santa Cruz", monday: "[object]"}
["[object]"]
{surfreport: "[array]"}
而2导致

{beach: "Santa Cruz", monday: "[object]"}
["[object]"]
{surfreport: "[array]"}
1导致

{beach: "Santa Cruz", monday: "[object]"}
["[object]"]
{surfreport: "[array]"}
这并不完美。如果对象中的字符串中有方括号或花括号,或者值不能为空(基本上,只有当它是函数或
未定义时,它才起作用)。也许有人(或我)会过来修复该功能。

[“1pm”、“2pm”、“3pm”]
更改为
对象.keys(surfing.surfreport[0]。星期一)
并且您不必提前知道名称…将
[“1pm”、“2pm”、“3pm”]
更改为
对象.keys(surfing.surfreport[0]。星期一)
而且您不必提前知道姓名。。。