22

I have a array called games with a value votes,

let games = [
    { id: 1, name: 'Star Wars: Imperial Assault', company: company.Fantasy_Flight, available: true, category: Category.SciFi, votes: 3},
    { id: 2, name: 'Game of Thrones: Second Edition', company: 'Fantassy Flight', available: false, category: Category.Fantasy, votes: 4 },
    { id: 3, name: 'Merchans and Marauders', company: 'Z-Man Gaming', available: true, category: Category.Pirates, votes: 5 },
    { id: 4, name: 'Eclipse', company: 'Lautapelit', available: false, category: Category.SciFi, votes: 6 },
    { id: 5, name: 'Fure of Dracula', company: 'Fantasy Flight', available: true, category: Category.Fantasy, votes: 2 }
]

I want to return the object with the most amount of votes. I've googled and found some methods using Math.max.apply, but it's returning the number of votes, and not the object itself.

function selectMostPopular():string {
    const allGames = getAllGames();
    let mostPopular: string = Math.max.apply(Math, allGames.map(function (o) { return o.votes; }));
    console.log(mostPopular);
    return mostPopular;
};

Any tips on how to return the object with the highest votes?

Peter Boomsma
  • 8,851
  • 16
  • 93
  • 185

4 Answers4

51

You can do a simple one-line reduce:

let maxGame = games.reduce((max, game) => max.votes > game.votes ? max : game);

Note: You should make sure games is not empty before you hit this code. As pointed out in the comments, this code will throw an error if games is empty.

(You could instead provide an initial value to .reduce to avoid the error. But it'll usually be most straightforward to check whether games is empty to begin with, rather than provide a dummy/default value and then later checking whether you got that dummy/default value.)

andyk
  • 1,628
  • 15
  • 12
  • 1
    Thanks for the answer. It's working like intended. Quick question though. What is the `max` in this context? – Peter Boomsma May 02 '16 at 06:07
  • 2
    `max` is always the game that has the most votes so far. If `game` has more votes than `max`, then it becomes `max` on the next iteration, and so on until the end of the array is reached. – andyk May 02 '16 at 18:26
  • This particular code will fail if `games` is empty [because](https://stackoverflow.com/questions/23359173/javascript-reduce-an-empty-array) no default value is provided to `.reduce`. – Wyck May 05 '21 at 19:21
10

You can use Array#map and Array#find

// First, get the max vote from the array of objects
var maxVotes = Math.max(...games.map(e => e.votes));

// Get the object having votes as max votes
var obj = games.find(game => game.votes === maxVotes);

(function () {
    var games = [{
        id: 1,
        name: 'Star Wars: Imperial Assault',
        company: 'company.Fantasy_Flight',
        available: true,
        category: 'Category.SciFi',
        votes: 3
    }, {
        id: 2,
        name: 'Game of Thrones: Second Edition',
        company: 'Fantassy Flight',
        available: false,
        category: 'Category.Fantasy',
        votes: 4
    }, {
        id: 3,
        name: 'Merchans and Marauders',
        company: 'Z-Man Gaming',
        available: true,
        category: 'Category.Pirates',
        votes: 5
    }, {
        id: 4,
        name: 'Eclipse',
        company: 'Lautapelit',
        available: false,
        category: 'Category.SciFi',
        votes: 6
    }, {
        id: 5,
        name: 'Fure of Dracula',
        company: 'Fantasy Flight',
        available: true,
        category: 'Category.Fantasy',
        votes: 2
    }];

    var maxVotes = Math.max(...games.map(e => e.votes));
    var obj = games.find(game => game.votes === maxVotes);
    console.log(obj);

    document.body.innerHTML = '<pre>' + JSON.stringify(obj, 0, 4);
}());
Tushar
  • 85,780
  • 21
  • 159
  • 179
3

What about sorting based on number of votes?

games.sort( function(a, b){
    return a.votes < b.votes; 
}); 

Now the first game in the array has the most votes.

KDot
  • 496
  • 2
  • 7
2

Just iterate, updating the maximum value and the object in which to find it when you find a greater value:

var max = -Infinity, argmax;
for(var game of games)
  if(game.votes >= max)
    max = game.votes, argmax = game;
argmax;
Oriol
  • 274,082
  • 63
  • 437
  • 513