Warm tip: This article is reproduced from stackoverflow.com, please click
javascript max

Top highest values in an object (more if there are more max values and they are the same)

发布于 2020-04-23 10:32:17

Lets suppose I have object like this:

var obj = {a : 5, b : 10, c : 15, d : 20, e : 20, f : 25};

I would like to get top 3 highest values - notice that d and e key have the same value and I need to get the keys also, so it would looks like:

Highest values:
f - 25
d - 20
e - 20

also if there are for example six values and four are identical:

var obj2 = {a:1, b:1, c:1, d:1, e:0,8, f: 0,5};

I need to show 4 highest.

Highest values:
a-1
b-1
c-1
d-1

I guess there is need to iterate over ALL object properties to get Math.max, but I also need a something to count 3 max numbers WITH their keys, and if there is more max (all the same) I need to "get them all!".

EDIT: there are great answers atm, so I guess I will not finish this code and just use given examples :)

Questioner
Proo1931
Viewed
13
fubar 2020-02-13 04:46

This is an example implementation, with annotations to explain what is happening at each step.

function maxValues(o, n) {
  // Get object values and sort descending
  const values = Object.values(o).sort((a, b) => b - a);
  
  // Check if more values exist than number required
  if (values.length <= n) return o;
  
  // Find nth maximum value
  const maxN = values[n - 1];
  
  // Filter object to return only key/value pairs where value >= maxN
  return Object.entries(o)
    .reduce((o, [k, v]) => v >= maxN ? { ...o, [k]: v } : o, {});
}

const a = maxValues({
  a: 5, 
  b: 10, 
  c: 15, 
  d: 20, 
  e: 20, 
  f: 25
}, 3);
console.log(a);

const b = maxValues({
  a: 1, 
  b: 1, 
  c: 1, 
  d: 1, 
  e: 0.8, 
  f: 0.5
}, 3);
console.log(b);

const c = maxValues({
  a: 5, 
  b: 10,
}, 3);
console.log(c);

The callback passed to the Array.prototype.reduce function can be expanded out to the following:

return Object.entries(o)
    .reduce(function (obj, [key, value]) {
        if (v >= maxN) {
            return Object.assign(obj, {
                [key]: value
            });
        } else {
            return obj;
        }
    }, {});

Instead, I condensed it down using an Arrow Function Expression, ternary operator, and spread syntax.

The ternary operator is essentially shorthand for an if/else statement. E.g.

condition ? true : false;
// or
v >= maxN ? { ...o, [k]: v } : o;

The spread syntax allows an iterable value to be expanded in place. In this instance, it's being used to copy existing key/value pairs from one object literal to another.

const a = { first_name: 'Rob', gender: 'male' };
const b = { ...a, username: 'fubar' };

console.log(b); // { first_name: 'Rob', gender: 'male', username: 'fubar' };