I am learning to filter nested arrays in javascript and I believe this example can help me to understand it better. below is the object.
const game = () => {
return {
player1: {
username: 'ABC',
playingAs: 'X'
},
player2: {
username: 'XYZ',
playingAs: '0'
},
board:
[
['✓', null, 'X'],
['X', '✓', null],
['✓', null, 'X']
]
}
};
my code is below
const {player1: {username: PlayerA, playingAs:PlayerAMark}, player2: {username: PlayerB, playingAs:PlayerBMark}} = game();
const {board: board} = game();
//is there any efficient way to do it without a loop using a filter?
for (const item in board) {
//One approach which comes to my mind is to loop. but that is what I don't think would be a learning curve for me.
}
I am trying something like this
const array = board;
for (const item in board) {
console.log(array.filter(innerArray => innerArray[item] !== 'X'));
}
I am focused on implementing some efficient way that can help me to return
Player1 marked 'X' at 3,1,3 and
Player 2 marked '0' at location at 0,2,1
I am only stuck with filtering this board multidimensional array.
I appreciate your help on this.
You can also use reduce function. We can have the desired output using this code:
function printForPlayer(player, board) {
var indexes = board.reduce((acc,row)=>[...row.reduce((acc2,item,index) => item==player.playingAs ? [...acc2,index+1] : acc2, []),...acc], [])
console.log(`${player.username} marked ${player.playingAs} at ${indexes.join(',')}`)
}
printForPlayer(game().player1, game().board);
printForPlayer(game().player2, game().board);
this is a bit complex, but it works without loop
One way is to loop over each row to create an array with all the places where the player has his own symbol.
Using reduce(), we can find all the indexes of the symobl of the current player, then after the loop, use join() to show it.
const data = {player1: {username: 'ABC', playingAs: 'X'}, player2: {username: 'XYZ', playingAs: '0'}, board: [['0', null, 'X'], ['X', '0', null], ['0', null, 'X'] ] };
const logPlayer = (player) => {
const ox = data[player].playingAs;
let indexes = [];
for (let row in data.board) {
const ii = data.board[row].reduce((prev, cur, i) => (cur === ox) ? [ ...prev, i ] : prev,[]);
if (ii.length > 0) ii.map(i => indexes.push(`${+row + 1}-${i + 1}`));
}
console.log(`${player} has placed an '${ox}' on the following places (row-column)`, indexes.join(", "));
}
logPlayer('player1');
logPlayer('player2');
player1 has placed an 'X' on the following places (row-column) 1-3, 2-1, 3-3
player2 has placed an '0' on the following places (row-column) 1-1, 2-2, 3-1
So here is my solution which worked for me.
First of all, null is always rendered as 0. So I hade to update my array as mentioned below
board:
[
['✓', null, 'X'],
['X', '✓', null],
['✓', null, 'X']
]
Secondly, after updating the board value in the array, the following solution worked for me.
const {
player1: {username: PlayerA, playingAs:PlayerAMark},
player2: {username: PlayerB, playingAs:PlayerBMark},
board: GameBoard
} = game();
let array = GameBoard.entries();
let tick = [];
let cross = [];
for (const [index,element] of array) {
tick.push(element.indexOf(PlayerBMark)+ 1);
cross.push(element.indexOf(PlayerAMark)+ 1);
}
console.log('Player ', PlayerA, ' Clicked ', PlayerAMark ,' at '+ cross);
console.log('Player ',PlayerB, ' Clicked ', PlayerBMark ,' at '+ tick);
Here is the result for this.
Player ABC Clicked X at 3,1,3
Player XYZ Clicked ✓ at 1,2,1
Thanks everyone for all the help. But, still I am looking for How we can improve its performance and avoided looping?
Thanks again.