0

I'm using an API to display stats of footballers, Using Javascript, I've currently got a 'for Loop' that goes through all of the players and displays them in a table.

What I'm looking to do is now find and display the players with the top stats - top scorers/most clean sheets/most red cards etc. How do I go about doing this?

Here's a sample of relevant JSON data from the API:

{
   "elements": [
        {
            "first_name": "Petr",
            "second_name": "Cech",
            "minutes": 585,
            "goals_scored": 0,
            "assists": 0,
            "clean_sheets": 1,
        },
        {
            "first_name": "Bernd",
            "second_name": "Leno",
            "minutes": 135,
            "goals_scored": 0,
            "assists": 0,
            "clean_sheets": 0,
        },
        {
            "first_name": "Mesut",
            "second_name": "Özil",
            "minutes": 510,
            "goals_scored": 2,
            "assists": 0,
            "clean_sheets": 2,
        },
        *(and on and on...)*
]}

There are around 500 players in this, so I need to have something that will go through all of them and work out which players have the highest values for each property name.

How can I get it so that I can (for example) show the top scorer, their goals and name. I'm not sure on the correct way to do this, whether it's to for loop through again and somehow do something with math.max?

Thanks!

1
  • Can the api sort that stuff for you? Commented Oct 19, 2018 at 20:01

5 Answers 5

2

This will loop over the array only once and retrieve all stats in one go:

const input = {
  "elements": [{
      "first_name": "Petr",
      "second_name": "Cech",
      "minutes": 585,
      "goals_scored": 0,
      "assists": 0,
      "clean_sheets": 1,
    },
    {
      "first_name": "Bernd",
      "second_name": "Leno",
      "minutes": 135,
      "goals_scored": 0,
      "assists": 0,
      "clean_sheets": 0,
    },
    {
      "first_name": "Mesut",
      "second_name": "Özil",
      "minutes": 510,
      "goals_scored": 2,
      "assists": 0,
      "clean_sheets": 2,
    }
  ]
};

const stats = input.elements.reduce((stats, player) => {
  ['minutes', 'goals_scored', 'assists', 'clean_sheets'].forEach(key => {
    if (player[key] > stats[key].max) {
      stats[key].max = player[key];
      stats[key].bestPlayer = player;
    }
  });
  return stats;
}, {
  minutes: {max: 0, bestPlayer: null}, 
  goals_scored: {max: 0, bestPlayer: null}, 
  assists: {max: 0, bestPlayer: null}, 
  clean_sheets: {max: 0, bestPlayer: null}
});

console.log('minutes', stats.minutes);
console.log('goals_scored', stats.goals_scored);
console.log('assists', stats.assists);
console.log('clean_sheets', stats.clean_sheets);

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the help and suggestions everyone!
2

You can sort the array and get the first element after the sorting process.

var object = {  "elements": [{      "first_name": "Petr",      "second_name": "Cech",      "minutes": 585,      "goals_scored": 0,      "assists": 0,      "clean_sheets": 1,    },    {      "first_name": "Bernd",      "second_name": "Leno",      "minutes": 135,      "goals_scored": 0,      "assists": 0,      "clean_sheets": 0,    },    {      "first_name": "Mesut",      "second_name": "Özil",      "minutes": 510,      "goals_scored": 2,      "assists": 0,      "clean_sheets": 2,    }  ]},
    lookFor = (arr, key) => {
      let sorted = arr.slice().sort((a, b) => {
        if (typeof a === 'string') {
          return b[key].localeCompare(a[key]);
        }

        return b[key] - a[key];
      });

      return sorted[0];
    }

console.log(lookFor(object.elements, 'goals_scored'));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Comments

0
function findMostPlayerByField(arr, fieldName, alt) {
    return arr.reduce((prevEl, el) => {
        if (!prevEl[fieldName]) {
            return el;
        } else if (alt) {
            return Number(prevEl[fieldName]) > Number(el[fieldName])? el: prevEl;
        } else {
            return Number(prevEl[fieldName]) < Number(el[fieldName])? el: prevEl;
        }
    }, {});
}

Example of usage:

findMostPlayerByField(elements, "minutes"); // Petr Chech object findMostPlayerByField(elements, "minutes", true); // Bernd Leno object

Comments

0

If you only want the top of each category, you can use Math.max in this fashion. Since there's a high likelihood that there will be a tie for leading scorer in particular, this method returns all players with that score.

If you're going to be working with multiple properties and a large input array, however, it would make more sense to handle it all in one loop, as seen in the second example.

var data = {
   "elements": [
        {
            "first_name": "Petr",
            "second_name": "Cech",
            "minutes": 585,
            "goals_scored": 0,
            "assists": 0,
            "clean_sheets": 1,
        },
        {
            "first_name": "Bernd",
            "second_name": "Leno",
            "minutes": 135,
            "goals_scored": 0,
            "assists": 0,
            "clean_sheets": 0,
        },
        {
            "first_name": "Mesut",
            "second_name": "Özil",
            "minutes": 510,
            "goals_scored": 2,
            "assists": 0,
            "clean_sheets": 2,
        }
]}

const maxScore = Math.max(...data.elements.map(t => t.goals_scored))

console.log(maxScore)

const leadingScorers = data.elements.filter(t => t.goals_scored == maxScore)

console.log(leadingScorers)

Second example:

const data = {
   "elements": [
        {
            "first_name": "Petr",
            "second_name": "Cech",
            "minutes": 585,
            "goals_scored": 0,
            "assists": 0,
            "clean_sheets": 1,
        },
        {
            "first_name": "Bernd",
            "second_name": "Leno",
            "minutes": 135,
            "goals_scored": 0,
            "assists": 0,
            "clean_sheets": 0,
        },
        {
            "first_name": "Mesut",
            "second_name": "Özil",
            "minutes": 510,
            "goals_scored": 2,
            "assists": 0,
            "clean_sheets": 2,
        }
]}

let len = data.elements.length

const topValues = {goals_scored: 0, assists: 0}, topPlayers = { goals_scored: [], assists: [] }, keys = Object.keys(topPlayers)

while(--len > -1){
  let player = data.elements[len]
  
  keys.forEach(key => {
    if(player[key] == topValues[key]) topPlayers[key].push(player.first_name + ' ' + player.second_name)
    else if(player[key] > topValues[key]){
      topPlayers[key] = [player.first_name + ' ' + player.second_name]
      topValues[key] = player[key]
    }
  })
}

console.log(topPlayers)

Comments

0

There have been a couple of good answers here like the one by @Ele and @Jeto. My answer is semantically same as @Jeto. However, I think it would be better to add some explanation. The code is given below:

const stats = {
"elements": [
     {
         "first_name": "Petr",
         "second_name": "Cech",
         "minutes": 585,
         "goals_scored": 0,
         "assists": 0,
         "clean_sheets": 1,
     },
     {
         "first_name": "Bernd",
         "second_name": "Leno",
         "minutes": 135,
         "goals_scored": 0,
         "assists": 0,
         "clean_sheets": 0,
     },
     {
         "first_name": "Mesut",
         "second_name": "Özil",
         "minutes": 510,
         "goals_scored": 2,
         "assists": 0,
         "clean_sheets": 2,
     },
]};

// for referring to highest in each category
// initially, the first stat is the highest 
let highest = {
 'highestGoals': stats.elements[0],
 'highestAssists': stats.elements[0],
 'highestCleanSheets': stats.elements[0]
}; 

for(let i=1; i<stats.elements.length; ++i) {
   let s = stats.elements[i];
   if(highest['highestGoals'].goals_scored < s.goals_scored) {
     highest['highestGoals'] = s; // this is the new highest scorer
   }
   if(highest['highestAssists'].assists < s.assists) {
     highest['highestAssists'] = s; // this is the new highest assists
   }
   if(highest['highestCleanSheets'].clean_sheets < s.clean_sheets) {
     highest['highestCleanSheets'] = s; // this is the highest clean sheets
   }
}

console.log(`Highest goal scorer: ${highest['highestGoals'].first_name + ' ' + highest['highestGoals'].second_name}`);
console.log(`Highest Assists: ${highest['highestAssists'].first_name + ' ' + highest['highestAssists'].second_name}`);
console.log(`Highest Clean Sheet: ${highest['highestCleanSheets'].first_name + ' ' + highest['highestCleanSheets'].second_name}`);

The code here makes a single pass through the array and identifies the highest achieving player on each category. This is exactly the same as a linear search algorithm. To support many keys, an array of keys can be used with a nested loop. If the length of the array is large, it will be wiser to use this solution or the one by @Jeto since, it does not sort the array for each search operation.

Hope this answers your question fully.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.