Получение наибольшего значения из JSON и отображение связанных данных (API / Javascript) - PullRequest
0 голосов
/ 19 октября 2018

Я использую API для отображения статистики футболистов. Используя Javascript, в настоящее время у меня есть «цикл», который просматривает всех игроков и отображает их в таблице.

Что яСейчас мне нужно найти и отобразить игроков с самой высокой статистикой - лучшие бомбардиры / самые чистые листы / большинство красных карточек и т. д. Как мне это сделать?

Вот пример соответствующих данных JSONиз 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...)*
]}

В нем около 500 игроков, поэтому мне нужно иметь что-то, что пройдет через них и определит, какие игроки имеют самые высокие значения для каждого имени свойства.

Как я могу получить его, чтобы я мог (например) показать лучшего бомбардира, его цели и имя.Я не уверен в правильном способе сделать это, будь то цикл for и снова что-то сделать с math.max?

Спасибо!

Ответы [ 5 ]

0 голосов
/ 19 октября 2018

Здесь было несколько хороших ответов, таких как @Ele и @Jeto.Мой ответ семантически совпадает с @Jeto.Тем не менее, я думаю, что было бы лучше добавить некоторые объяснения.Код приведен ниже:

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}`);

Код здесь делает один проход по массиву и идентифицирует highest игрока, достигшего достижения в каждой категории.Это точно так же, как алгоритм линейного поиска.Для поддержки многих ключей можно использовать массив ключей с вложенным циклом.Если длина массива велика, будет разумнее использовать это решение или решение @Jeto, поскольку он не сортирует массив для каждой операции поиска.

Надеюсь, что это полностью отвечает на ваш вопрос.

0 голосов
/ 19 октября 2018

Если вы хотите только верхнюю часть каждой категории, вы можете использовать Math.max таким образом.Поскольку существует высокая вероятность того, что, в частности, победит ведущий бомбардир, этот метод возвращает всех игроков с таким счетом.

Однако, если вы собираетесь работать с несколькими свойствами и большим входным массивом., было бы более разумно обрабатывать все это в одном цикле, как видно во втором примере.

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)

Второй пример:

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)
0 голосов
/ 19 октября 2018

Это зацикливает массив только один раз и извлекает всю статистику за один раз:

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);
0 голосов
/ 19 октября 2018
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;
        }
    }, {});
}

Пример использования:

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

0 голосов
/ 19 октября 2018

Вы можете отсортировать массив и получить первый элемент после процесса сортировки.

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; }
...