Reputation: 9106
I have a multiplayer game and the gameplay data is stored like this:
var gameplays = [
{id: "1", player1: "bob", player2: "tim", score1: 2, score2: 14},
{id: "2", player1: "bob", player2: "tim", score1: 7, score2: 3},
{id: "3", player1: "bob", player2: "tim", score1: 6, score2: 10},
{id: "4", player1: "bob", player2: "tim", score1: 5, score2: 1}
];
What is the most efficient way to find the top 5 highscores from all the games by searching "score1" and "score2" and output them like this:
HIGHSCORES
1. Tim - 14
2. Tim - 10
3. Bob - 7
4. Bob - 6
5. Bob - 5
Upvotes: 0
Views: 80
Reputation: 1783
If you'r going to benchmark this I would be interested in the performance of the "functional" kind of solution with Ramda.
var gameplays = [
{id: "1", player1: "bob", player2: "tim", score1: 2, score2: 14},
{id: "2", player1: "bob", player2: "tim", score1: 7, score2: 3},
{id: "3", player1: "bob", player2: "tim", score1: 6, score2: 10},
{id: "4", player1: "bob", player2: "tim", score1: 5, score2: 1}
];
// find the 5 top highscores regardless which player
const normalizeScore = ({id, player1, score1, player2, score2}) =>
[{id, player1, score: score1}, {id, player2, score: score2}];
const sortByScore = (play1, play2) => play2.score - play1.score;
const normalizeGameplays = R.chain(normalizeScore); // chain === flatMap
const sortGameplays = R.sort(sortByScore);
const topFive = R.slice(0, 5);
const highscore = R.compose(topFive, sortGameplays, normalizeGameplays);
console.log(highscore(gameplays));
@See: https://jsbin.com/wixowu/edit?html,js,console
Upvotes: 0
Reputation: 84
const gameplays = [
{id: "1", player1: "bob", player2: "tim", score1: 2, score2: 14},
{id: "2", player1: "bob", player2: "tim", score1: 7, score2: 3},
{id: "3", player1: "bob", player2: "tim", score1: 6, score2: 10},
{id: "4", player1: "bob", player2: "tim", score1: 5, score2: 1}
];
First, write all relevant game information into an array of objects, each of which contain a player key corresponding to the player's name and a score key, which corresponds to the score:
const results = [];
gameplays.forEach(game => {
for(let i = 1; i <= 2; i++) {
results.push({});
results[results.length - 1].player = `${game[`player${i}`].slice(0, 1).toUpperCase()}${game[`player${i}`].slice(1).toLowerCase()}`;
results[results.length - 1].score = game[`score${i}`];
}
});
Then, sort the array in descending order of scores before only keeping the top 5 with slice.
const topFive = results.sort((result1, result2) => result2.score - result1.score)
.slice(0, 5);
Finally, display the top 5 scores.
console.log('High Scores');
for(let i = 0; i < topFive.length; i++) {
console.log(`${i + 1}. ${topFive[i].player} - ${topFive[i].score}`);
}
Upvotes: 1
Reputation: 2473
You can do it in a sort pretty easily I think with:
gameplays.sort(function(_a, _b){
var a = _a.score1 > _a.score2 ? _a.score1 : _a.score2;
var b = _b.score1 > _b.score2 ? _b.score1 : _b.score2;
if(a < b) {
return 1;
}
if(a > b) {
return -1;
}
return 0;
})
Then, you you can access the top five with:
gameplays.slice(0, 5)
Upvotes: 0
Reputation: 1616
var scores = [];
for (var i = 0; i < gameplays.length; i++) {
scores.push({score: gameplays[i].score1, name: gameplays[i].player1});
scores.push({score: gameplays[i].score2, name: gameplays[i].player2});
}
scores.sort(function (a, b) {
return b.score - a.score;
});
scores.splice(0, 5);
First, get the scores and flatten them in a scores array along with score and name of individual.
Then, we sort the array and splicing will get the top 5 scores with name.
Upvotes: 3