Reputation: 71
This is my first time asking a question here. I'm new to JavaScript and I'm trying learn it by making a game. I have 5 players, each with a scoreHistory array. How do I sort through all the player's scores, and display only the top 10? Since there are only 5 players, some players should be displayed multiple times if they have many high scores.
const Data = [
{
username: 'spidey2016',
email: '[email protected]',
password: 'maryJane123',
firstName: 'Peter',
lastName: 'Parker',
scoreHistory: [500, 2300, 1000, 900, 3000],
},
{
username: 'bbanner45',
email: '[email protected]',
password: 'berttyRoss456',
firstName: 'Bruce',
lastName: 'Banner',
scoreHistory: [1000, 3500, 800, 2000, 3100],
},
{
username: 'weirdo100',
email: '[email protected]',
password: 'chritinePalmer789',
firstName: 'Stephen',
lastName: 'Strange',
scoreHistory: [2000, 700, 1000, 1000, 500],
},
{
username: 'merchantOfDeath',
email: '[email protected]',
password: 'pepperPotts123',
firstName: 'Tony',
lastName: 'Stark',
scoreHistory: [3000, 2500, 1000, 3100, 800],
},
{
username: 'hammerGod',
email: '[email protected]',
password: 'janeFoster456',
firstName: 'Thor',
lastName: 'Odinson',
scoreHistory: [500, 900, 1100, 2500, 2900],
},
]
export default Data;
What I've been able to do is sort through my data and get each player's top score and sort them from highest to lowest. But, I realized that some players have multiple high scores and should be displayed multiple times.
import React from 'react';
import { connect } from 'react-redux'
// hard code list of high scores - top 10
const HighScores = (props) => {
return (
<div>
<h1>High Scores</h1>
<table className="table table-striped">
<thead>
<tr>
<th>#</th>
<th>Username</th>
<th>High Score</th>
</tr>
</thead>
<tbody>
{props.user.sort((a, b) => Math.max(...b.scoreHistory) - Math.max(...a.scoreHistory)).map((user, index) => //sort through all players based on their top scores them display them in order top to last
<tr key={index}>
<th>{index + 1}</th>
<td>{user.username}</td>
<td>{Math.max(...user.scoreHistory)}</td>
</tr>
)}
</tbody>
</table>
</div>
);
}
const mapStateToProps = state => ({
user: state.users,
allScores: state.allScores
})
export default connect(mapStateToProps)(HighScores);
Upvotes: 3
Views: 1021
Reputation: 386730
You could take a staged approach and take all scores and the names and sort this array and take the top ten items.
var data = [{ username: 'spidey2016', email: '[email protected]', password: 'maryJane123', firstName: 'Peter', lastName: 'Parker', scoreHistory: [500, 2300, 1000, 900, 3000] }, { username: 'bbanner45', email: '[email protected]', password: 'berttyRoss456', firstName: 'Bruce', lastName: 'Banner', scoreHistory: [1000, 3500, 800, 2000, 3100] }, { username: 'weirdo100', email: '[email protected]', password: 'chritinePalmer789', firstName: 'Stephen', lastName: 'Strange', scoreHistory: [2000, 700, 1000, 1000, 500] }, { username: 'merchantOfDeath', email: '[email protected]', password: 'pepperPotts123', firstName: 'Tony', lastName: 'Stark', scoreHistory: [3000, 2500, 1000, 3100, 800] }, { username: 'hammerGod', email: '[email protected]', password: 'janeFoster456', firstName: 'Thor', lastName: 'Odinson', scoreHistory: [500, 900, 1100, 2500, 2900] }],
top10 = data
.reduce((r, { username, scoreHistory }) => r.concat(
scoreHistory.map(score => ({ username, score }))
), [])
.sort(({ score: a }, { score: b }) => b - a)
.slice(0, 10);
console.log(top10);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 1
Reputation: 2153
This is how you can do it:
{ player: username, score: score }
const data = [
{
username: 'spidey2016',
email: '[email protected]',
password: 'maryJane123',
firstName: 'Peter',
lastName: 'Parker',
scoreHistory: [500, 2300, 1000, 900, 3000],
},
{
username: 'bbanner45',
email: '[email protected]',
password: 'berttyRoss456',
firstName: 'Bruce',
lastName: 'Banner',
scoreHistory: [1000, 3500, 800, 2000, 3100],
},
{
username: 'weirdo100',
email: '[email protected]',
password: 'chritinePalmer789',
firstName: 'Stephen',
lastName: 'Strange',
scoreHistory: [2000, 700, 1000, 1000, 500],
},
{
username: 'merchantOfDeath',
email: '[email protected]',
password: 'pepperPotts123',
firstName: 'Tony',
lastName: 'Stark',
scoreHistory: [3000, 2500, 1000, 3100, 800],
},
{
username: 'hammerGod',
email: '[email protected]',
password: 'janeFoster456',
firstName: 'Thor',
lastName: 'Odinson',
scoreHistory: [500, 900, 1100, 2500, 2900],
},
]
const scores = data.map(player => {
return player.scoreHistory.map(score => {
return {
player: player.username,
score,
}
})
}).flat()
const highestScores = scores.sort((a, b) => b.score - a.score).slice(0, 5)
const list = document.querySelector('.top-scores')
highestScores.forEach(({ player, score }) => {
const el = document.createElement("li")
el.innerText = `${player} ${score}`
list.appendChild(el)
})
<ul class="top-scores">
</ul>
Upvotes: 0
Reputation: 1627
One way you can achieve this is like this:
First you create a new array scores
, consisting of (score, player) pairs:
let scores = [];
Data.forEach(entry => {
entry.scoreHistory.forEach(score => {
scores.push({score:score, player:entry.username});
});
});
Then you sort this array descending by score
scores.sort((a, b) => b.score - a.score);
And now you only need to iterate over your top 10 and print the output:
for (let i = 0; i < 10; i++) {
console.log(scores[i]);
}
Upvotes: 0
Reputation: 7492
Seems like a school exercise. Here are the steps you need to implement :
First, map every score in your players score histories to the following object :
{
username: String,
score: Number
}
You can achieve this by using the map function
Then flatten your array by either deconstructing your data or using flat / concat
Finally, you can use sort
to sort out the biggest score with each object also indicating the name of the player who did it
Upvotes: 0