在 Node.js/Javascript 中,如何检查多维数组中是否存在某个值?

4
假设我有一个这样的数组:
$game = Array
(
    ['round'] => Array
        (
            ['match'] => Array
                (
                    ['player_2'] => Array
                        (
                            [name] => asddd
                            [id] => 1846845
                            [winner] => yes
                        )

                    ['player_21'] => Array
                        (
                            [name] => ddd
                            [id] => 1848280
                            [winner] => no
                        )

                )
        )
)

假设在Node.js/Javascript中,我需要检查player_3winner键值是否为yes。在PHP中,您可能会这样做:

if( $game['round']['match'][player_3]['winner'] == 'yes'){

}

由于 PHP 中没有 player_3,所以会返回 false。但如果我在 JavaScript 中进行类似的操作:
 if( typeof game['round']['match'][player_3]['winner'] != 'undefined' && game['round']['match'][player_3]['winner'] == 'yes'){

 }

我会得到错误:(node:15048) UnhandledPromiseRejectionWarning: TypeError: Cannot read property '0' of undefined,原因是player_3在数组中不存在,你不能检查一个不存在的数组的键值。

在Javascript中,你可以这样做:

if( 
   typeof game['round'] != 'undefined' &&
   typeof game['round']['match'] != 'undefined' &&
   typeof game['round']['match']['player_3'] != 'undefined' &&
   typeof game['round']['match']['player_3']['winner'] != 'undefined' &&
   typeof game['round']['match']['player_3']['winner'] == 'yes'
){
   var playerIsWinner = true;
}else{
   var playerIsWinner = false;
}

您需要逐层检查数组的存在。我不知道它是否实际上有效,但即使有效,这看起来是一种不好且愚蠢的方式来检查某些东西。我的意思是看看在PHP中它是多么简单,而在JavaScript中我必须检查数组内每个数组的存在。所以,有没有更好的方法来检查数组的值呢?

你可以将它包裹在一个 try...catch 块中。 - Luca Kiebel
1
可能是[如何检查数组是否具有定义值的嵌套属性]的重复问题(https://stackoverflow.com/questions/46221381/how-to-check-if-array-has-nested-property-with-defined-value)。 - fsinisi90
5个回答

2
请看一下lodash库,特别是像get这样的方法。然后你可以安全地尝试一些类似于以下的东西:
_.get(game, 'round.match.player3.winner', false);

这就是了 :)

1
您展示的数组更像是JS中的一个对象。因此,这里是您可能尝试的内容。
const obj = {
  round: {
    match: {
      player_2: {
        name: 'asddd',
        id: 1846845,
        winner: true
      },
      player_21: {
        name: 'ddd',
        id: 1848280,
        winner: false
      }
    }
  }
}

...

const isWinner = (key) => {
  try {
    return obj.round.match[key].winner
  } catch(e) {
    return false
  }
}


console.log(isWinner('player_2'))

通过将返回值包装在 try ... catch 中,您可以防止错误在查询时被抛出,可能会导致应用程序停止运行。如果由于任何原因您的对象结构发生更改,仍将返回布尔值。
如果必须以字符串形式保留您的 winner 值,则可以简单地比较该值,最终将得到布尔值作为结果。如下所示:
const isWinner = (key) => {
  try {
    return (obj.round.matchs[key].winner === 'yes')
  } catch(e) {
    return false
  }
}

我认为在这种情况下使用类似于lodash的东西会更简单、更安全。而且它也更易读。你介意吗? - Artem
它肯定会更短,甚至可能更容易应用。但我不认为它会更可读,特别是如果你不熟悉 lodash。而且,说实话,我不会只为了使用一次就忘记它而安装 lodash - Patryk Cieszkowski

1

你不需要为深度嵌套数据的 nullundefined 进行手动检查,相反,你可以在这种情况下推出自己的小而紧凑的函数 get 并且对于提供的任何输入数据都可以灵活处理。更多关于 Array.prototype.reduce() 的信息请参见。

// this single line will do the trick
const get = (p, o) =>p.reduce((xs, x) => (xs && xs[x]) ? xs[x] : null, o)

// let's pass in our props object...

const props = {"round":{"match":[{"player_21":{"name":"asdfg","id":1846845,"winner":"not yet"}},{"player_2":{"name":"sany","id":1846280,"winner":"no"}},{"player_3":{"name":"sunny","id":1846000,"winner":"yes"}}]}}

var playerIsWinner = false;
//console.log(get(['round', 'match', 2, 'player_3', 'winner'], props))
if (get(['round', 'match', 2, 'player_3', 'winner'], props) == 'yes') {
  playerIsWinner = true;
}

console.log(playerIsWinner)


0
您可以采取以下措施避免未定义错误:
 if ( game['round']['match'][player_3] && game['round']['match'][player_3]['winner'] == 'yes' ) {
   ...
 }

因为 undefined 是“假值”,所以如果 player_3 不存在,您将得到 false 而不是 undefined,如果 player_3 存在并且是赢家,则返回 true。


0

只需将代码放在 try catch 块中即可。这样可以跳过所有样板文件中的 typeof 语句:

   typeof game['round'] != 'undefined' &&
   typeof game['round']['match'] != 'undefined' &&
   typeof game['round']['match']['player_3'] != 'undefined' &&
   typeof game['round']['match']['player_3']['winner'] != 'undefined' &&
   typeof game['round']['match']['player_3']['winner'] == 'yes'

如果元素不存在,则抛出错误并处理它。例如:

let nestedObj = {
  prop1: {
    propa1: {
      propb1: 'test'
    }
  },
  prop2: {}
}

try {
  console.log(nestedObj['prop1']['propa1']['propb1']);
  console.log(nestedObj['prop2']['propa2']['propb2']);
} catch(e) {
  console.log('prop not defined');
}

这比你现在做的检查每个简单条件要简单得多。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接