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 :)
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' };
can you elaborate more on "v >= maxN ? { ...o, [k]: v } : o, {}" I have used you code (and it works fine!) but I have problem with... understanding it :) I have never seen Conditional Operator that looks like that. Reduce has got "['a' : 5]" as 'o' (accumulator) and "['b' : 10]" as currentValue. What are the arguments after first loop? Damn this code is so sophisticated for me :)
@Proo1931 - I've edited my answer to include more explanation around the code used and with links to the relevant MDN pages for a more indepth explanation. I hope this helps.
whoaaa excellent description. Everything is clear now (you have described EVERY question I had in mind - so I start to believe in telepathy :). I just didn't know that you can write a function for TWO arguments, and then add the THIRD one (in the reduce method). I did use debugger and check my results estimations in every step of the code evaluation and I understand everything. Thanks, I have learned a lot!