Hith
Hith

Reputation: 448

Getting keys with maximum value in JavaScript hashmap/object

Example:

hash = {'Apple':2, 'Orange' :1 , 'Mango' : 2}

here the maximum key is both Apple and Mango. How do I write a function which gives both Apple and Mango as answer.

I tried something like this :

Object.keys(hash).reduce(function(a, b){ return hash[a] > hash[b] ? a : b });

But this gives only Apple as the answer.

Upvotes: 5

Views: 5774

Answers (5)

D. Seah
D. Seah

Reputation: 4592

I believe the requirements are traverse the array only once and results is an array of keys

const hash = {'Apple':2, 'Orange' :1 , 'Mango' : 2};
let max = 0;
let result = [];

Object.getOwnPropertyNames(hash).forEach(k => {
  if (hash[k] > max) {
    result = [k];
    max = hash[k];
  } else if (hash[k] === max) {
    result.push(k);
  }
});

console.log(result);

Upvotes: 0

Vignesh Raja
Vignesh Raja

Reputation: 8761

This works. If max changes clear the result and set only the max value.

var hash = {'Apple':2, 'Orange':1 , 'Mango':2, "Jackfruit":10, "Pineapple":5, "Tomato":-4};
var max="";

var result = Object.keys(hash).reduce(function(acc, val){
    if(max < hash[val]) (max=hash[val], acc={});
    if(hash[val]==max) acc[val] = hash[val];
    return acc;
},{});

console.log(result)

Upvotes: 0

Robby Cornelissen
Robby Cornelissen

Reputation: 97162

You could first calculate the max value as a separate operation and then just filter:

const hash = {Apple: 2, Orange: 1, Mango: 2};

const max = Object.keys(hash).reduce((a, v) => Math.max(a, hash[v]), -Infinity);
const result = Object.keys(hash).filter(v => hash[v] === max);

console.log(result);

Simple and readable, but it requires and extra iteration, so it's not the most efficient implementation.

Upvotes: 4

CertainPerformance
CertainPerformance

Reputation: 370879

You might transform the object into one whose properties correspond to the count, whose values are the (original) property names in an array, and then get the value of the property with the maximum count:

const hash = {'Apple':2, 'Orange' :1 , 'Mango' : 2};
const indexedByCount = Object.entries(hash).reduce((a, [key, val]) => {
  if (!a[val]) a[val] = [];
  a[val].push(key);
  return a;
}, {});
console.log(
  indexedByCount[Math.max(...Object.keys(indexedByCount))]
);

A less functional but more efficient method would be to keep track of a max variable corresponding to the maximum value found so far:

const hash = {'Apple':2, 'Orange' :1 , 'Mango' : 2};
let max = -Infinity;
console.log(
  Object.entries(hash).reduce((a, [key, val]) => {
    if (val > max) {
      max = val;
      return [key];
    }
    if (val === max) a.push(key);
    return a;
  }, [])
);

Upvotes: 1

Sebastian Simon
Sebastian Simon

Reputation: 19485

Your reduce can only return a single value, but you need an array of values. So create one as the initial value.

In your function body, first, check whether your next key has a larger value, in which case you clear out the array.

Then, if your array is empty, or if the first contained key (and thus all keys) have the same value, push that key into your array.

Also, it helps if you give your arguments more expressive names.

Object.keys(hash).reduce(function(longestKeys, key){
  if(hash[key] > hash[longestKeys[0]]){
    longestKeys.length = 0;
  }

  if(longestKeys.length === 0 || hash[key] === hash[longestKeys[0]]){
    longestKeys.push(key);
  }

  return longestKeys;
}, []);

Upvotes: 1

Related Questions