0
var leaderboard = [{userId: 10293, balance: 1023},
                   {userId: 20394, balance: 1806},
                   {userId: 45333, balance: 2064},
                   {userId: 57456, balance: 2453},
                   {userId: 24575, balance: 2703}
                  ];

I have this object and want to create a function that searches to see if a user is already added by checking all the userIds. If they do exist I want to update their specific balance to a new one, in my case it will be msg.userBalance. If they don't exist I want to check if their balance is greater than any one of the balances currently in the object, and if so I want to add them to it and remove the 6th one with the lowest balance.

leaderboard.map(function(person) {
  if (person.userId == msg.userId) {
    person.balance = msg.userBalance
  } else {
    if (currentBalance > //other 5 balances in object { 
      leaderboard.push({userId: msg.userId, balance: msg.userBalance});
    }
  }
});

I'm a bit stuck and I know I'm in the right direction but obviously missing a big part of the equation. I'm not opposed to using jQuery I'm just looking for the most simple solution. Help?

nickytonline
  • 6,855
  • 6
  • 42
  • 76
user3473543
  • 131
  • 1
  • 10

4 Answers4

2

I think this will do what you want,,

var user = leaderboard.filter(function(user){return userId == msg.userId})[0];
if(user){
   user.balance = msg.userBalance;
} else {
   leaderboard.push({userId: msg.userId, balance: msg.userBalance});
   leaderboard.sort(function(a,b){return a.balance-b.balance});
   leaderboard.shift();     
}

what i did here is ,, I used filter to get the user that matches your target user id ,, and if it wasn't found ,, I add it to the array ,, and then sort the array ascending ,, and then remove the first element ,, which will be the lowest one

Ahmed Eid
  • 1,145
  • 8
  • 9
1

This might not be the most efficient, but it's late and I'm tired.

var lowest = Number.POSITIVE_INFINITY;             // set the lowest value to something really high
$.each(leaderboard, function(idx,item){            // get the lowest value
    if(item.balance < lowest){
        lowest = item.balance;
    }
});

var i = $.grep(leaderboard, function(item){        // get the item based on userId, if it already exists
    return item.userId == msg.userId;
})[0];

if(!i){                                                     // if it doesnt exist...
    if(msg.userBalance > lowest){                           // if the new items balance is greater than the lowest one
        leaderboard.push(msg);                              // add it
        leaderboard = $.grep(leaderboard, function(item){   // and remove the item with the lowest value from the array
            return item.balance != lowest;
        });
    }
} else {                                           // if it does exists
    i.balance = msg.userBalance;                   // update the balance
}

Here's a working fiddle.

It's probably possible to get it working the way you've started out - I've just never been a fan of $.map, for no reason in particular. This solution is just one of many dozen ways it could be done, and might help give you an idea about the logic required.

Dave Salomon
  • 3,287
  • 1
  • 17
  • 29
0

The solution passes through the array at a time. But we need to go through once in the beginning to initialize the value of the subsidiary.

    leaderboard.max = -Infinity; // Set max balance
    leaderboard.min = Infinity; // Set min balance
    leaderboard.forEach( function( item, index, self ) {
        if (item.balance>self.max) self.max = item.balance;
        if (item.balance<self.min) self.min = item.balance;    
    });

    leaderboard.updateBalance = function ( userId, newBalance ) {
        var updated = false;
        var minIndex1 = -Infinity;
        var minIndex2 = Infinity;
        this.forEach( function( item, index, self ) {

            // Find 2 index with minimal balance
            if (item.balance === self.min) minIndex1 = index;
            if (item.balance > self.min && item.balance < minIndex2) minIndex2 = index;

            // If find user - update balance and min and max
            if (item.userId === userId) {
                updated = true; // Flag - user balance updated
                self[index].balance = newBalance;
                if (newBalance > self.max) self.max = newBalance;
                if (newBalance < self.min) self.min = newBalance;            
            }
        });

        // No user find? Push
        if (!updated && newBalance > leaderboard.max) {
            this.min = this[minIndex2].balance;
            if (this.length===5) this.splice(minIndex1, 1); // Remove user with minimal balance
            this.max = newBalance;
            this.push( { userId: userId, balance: newBalance } );
        }
    };

https://jsfiddle.net/5cfyLodp/

stdob--
  • 28,222
  • 5
  • 58
  • 73
0

You might like to consider restructuring your list of objects as a hash table. It has all the makings of a good one, as your objects are just key-value pairs.

Then you can more powerfully and simply refer to your balances by their keys to achieve what you're after.

// Initialise hash table
var leaderboard = {
    {10293, 1023}
    {20394, 1806},
    {45333, 2064},
    {57456, 2453},
    {24575, 2703}
};

// Initialise person and msg somewhere

// If the person exists already, update their balance
if(leaderboard[person.userId] != null) {
    leaderboard[person.userId] = msg.userBalance;
    return; // Return early, we've done our work
}

// If the person's balance is greater than any of the others in the hash, replace them
for(var i in leaderboard) {
    if(leaderboard[i] < msg.userBalance) {
        delete leaderboard[i];
        leaderboard[person.userId] = msg.userBalance
    }
}
Jamie Butler
  • 235
  • 1
  • 2
  • 19