Reputation: 517
Lets say I have array something like this:
$game = Array
(
['round'] => Array
(
['match'] => Array
(
['player_2'] => Array
(
[name] => asddd
[id] => 1846845
[winner] => yes
)
['player_21'] => Array
(
[name] => ddd
[id] => 1848280
[winner] => no
)
)
)
)
And lets say in Node.js/Javascript I need to check if player_3
winner
key value is yes
. In PHP, you did something like this:
if( $game['round']['match'][player_3]['winner'] == 'yes'){
}
Because there is no player_3
it returns false in PHP, but if I did something similar in Javascript:
if( typeof game['round']['match'][player_3]['winner'] != 'undefined' && game['round']['match'][player_3]['winner'] == 'yes'){
}
I would get error: (node:15048) UnhandledPromiseRejectionWarning: TypeError: Cannot read property '0' of undefined
, because player_3
doesn't exist in array and you can't check key value of array, that doesn't exist.
You could do this in 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;
}
You check each array inside array from top down and make sure that they exists. I don't know if it actually works, but even if it does, it seems bad and stupid way to check something. I mean look how simple it is in PHP, while in Javascript I have to check each array existence inside array. So is there better way checking value of array?
Upvotes: 4
Views: 3466
Reputation: 2047
Please, look at the lodash library, especially at methods, such as get. Then you may safely try something like:
_.get(game, 'round.match.player3.winner', false);
That's it :)
Upvotes: 2
Reputation: 38532
No you don't need to do manual check for deeply nested data for null
or undefined
, instead you could rollout your own small but compact function in this case get
and be flexible with any input data provided. See more about 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)
Upvotes: 1
Reputation: 751
The array you've shown resembles more of an object in JS. So here's what you could possibly try.
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'))
By wrapping your return inside of try ... catch
, you prevent the error from being thrown at your query and possibly stopping the app from continuing on. If from whatever reason the structure of your object would change, you'd still have a boolean value returned.
If you have to keep your winner
value in form of a string, you could simply compare the value, and you'll end up with boolean as a result. As so:
const isWinner = (key) => {
try {
return (obj.round.matchs[key].winner === 'yes')
} catch(e) {
return false
}
}
Upvotes: 1
Reputation: 36630
Just wrap in a try catch
block. This allows you to skip all of your boilerplate typeof
statements:
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'
Instead throw an error and handle it if a element is not present. For example:
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');
}
This is a lot simpler than checking for every simple condition like you are doing now.
Upvotes: 0
Reputation: 1158
You can do the following to avoid the undefined error:
if ( game['round']['match'][player_3] && game['round']['match'][player_3]['winner'] == 'yes' ) {
...
}
Because undefined is "falsey" you'll get false instead of undefined if player_3 does not exist, and true if player_3 exists and is the winner.
Upvotes: 0