How can I remove an object from array of objects based on max value in javascript

  • A+
Category:Languages

I've got an array of objects that looks like this:

[ { person: 'Fred', scoreTotal: 29 }, { person: 'Alice', scoreTotal: 34 }, { person: 'Alice', scoreTotal: 22 }, { person: 'Mary', scoreTotal: 14 }, { person: 'Bob', scoreTotal: 33 }, { person: 'Bob', scoreTotal: 13 }, { person: 'Bob', scoreTotal: 22 }, { person: 'Joe', scoreTotal: 28 }] 

and where there are multiple objects for a given person -> I want to keep the top "X". For example:

a. top 1 result for a person Result would look like this:

    [ { person: 'Fred', scoreTotal: 29 },     { person: 'Alice', scoreTotal: 34 },     { person: 'Mary', scoreTotal: 14 },     { person: 'Bob', scoreTotal: 33 },     { person: 'Joe', scoreTotal: 28 }] 

b. top 2 results for a person Result would look like this:

   [ { person: 'Fred', scoreTotal: 29 },   { person: 'Alice', scoreTotal: 34 },    { person: 'Alice', scoreTotal: 22 },    { person: 'Mary', scoreTotal: 14 },    { person: 'Bob', scoreTotal: 33 },    { person: 'Bob', scoreTotal: 22 },    { person: 'Joe', scoreTotal: 28 }] 

Is there a way to achieve this using something like Lodash?

I think I'm heading in the right direction with this but not quite there yet:

for (var i = 0; i < t.length - 1; i++) { if (   t[i].golfer === t[i + 1].golfer &&   t[i].scoreTotal < t[i + 1].scoreTotal ) {   delete t[i]; } 

}

// remove the "undefined entries"

t = t.filter(function(el) {     return typeof el !== "undefined"; }); console.log(t); 

 


This does exactly what you want in the exact order you want using the exact library you're trying to use (lodash). I broke the process down into the following steps:

Step 1: group the data. There should be a an array containing all "Bob" records, and another array containing all "Joe" records, etc. I decided to go a step further and only store the scoreTotal rather than the entire record.

Step 2: loop through each of these arrays, sort them in descending order, and slice to the desired "top" results.

Step 3: filter the original data, using our previous findings and only include a record in the results if we have an exact scoreTotal match for a specific person, and only once per such score, removing it from our temporary array along the way so we don't get duplicate records and return more records than the "top" records desired.

// The magical function function showTopResults(input, topResults) {   // Step one: group like data together  var groupedData = _.reduce(input, function(result, value, key) {      if(typeof result[value.person] == 'undefined'){ result[value.person] = []; }      result[value.person].push(value.scoreTotal);      return result;  }, {});    // Step two: loop through person keys, sort it, then grab only the first "x" elements  _.forEach(groupedData, function(value, key) {     value = value.sort(function(a,b){ var n = b - a; return n ? n < 0 ? -1 : 1 : 0}); // first element is largest     groupedData[key] = value.slice(0, topResults); // we only want first x results, so we get largest only  });    // Step three: filter our elements only where we have a match  var filterResults = _.filter(input,function(o){   var idx = _.indexOf(groupedData[o.person],o.scoreTotal);   if( idx > -1)   {    groupedData[o.person].splice(idx, 1); // remove element so we don't get multiple elements of equal value    return true; // We have a match   } else {    return false; // not a match   }  });   return filterResults;  }  // Our input var input = [  { person: 'Fred', scoreTotal: 29 },  { person: 'Alice', scoreTotal: 34 },  { person: 'Alice', scoreTotal: 22 },  { person: 'Mary', scoreTotal: 14 },  { person: 'Bob', scoreTotal: 33 },  { person: 'Bob', scoreTotal: 13 },  { person: 'Bob', scoreTotal: 22 },  { person: 'Joe', scoreTotal: 28 } ];  // Tests using our magical function console.log(showTopResults(input, 1)); console.log(showTopResults(input, 2));
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: