Y2theZ
Y2theZ

Reputation: 10412

Fast way to get the min/max values among properties of object

I have an object in javascript like this:

{ "a":4, "b":0.5 , "c":0.35, "d":5 }

Is there a fast way to get the minimum and maximum value among the properties without having to loop through them all? because the object I have is huge and I need to get the min/max value every two seconds. (The values of the object keeps changing).

Upvotes: 130

Views: 209033

Answers (16)

KARTHIKEYAN.A
KARTHIKEYAN.A

Reputation: 20088

If we are sorting date time value then follow the below described procedure

const Obj = {
    "TRADE::Trade1": {
        "dateTime": "2022-11-27T20:17:05.980Z",
    },
    "TRADE::Trade2": {
        "dateTime": "2022-11-27T20:36:10.659Z",
    },
    "TRADE::Trade3": {
        "dateTime": "2022-11-27T20:28:10.659Z",
    }
} 


const result = Object.entries(Obj).sort((prev, next) => new Date(prev[1].dateTime) - new Date(next[1].dateTime))

console.log(result)

Upvotes: 0

Hammed Noibi
Hammed Noibi

Reputation: 81

To get the keys for max and min

var list = { "a":4, "b":0.5 , "c":0.35, "d":5 };
var keys = Object.keys(list);
var min = keys[0]; // ignoring case of empty list for conciseness
var max = keys[0];
var i;

for (i = 1; i < keys.length; i++) {
    var value = keys[i];
    if (list[value] < list[min]) min = value;
    if (list[value] > list[max]) max = value;
}

console.log(min, '-----', max)

Upvotes: 5

AHMED RABEE
AHMED RABEE

Reputation: 481

   obj.prototype.getMaxinObjArr = function (arr,propName) {
        var _arr = arr.map(obj => obj[propName]);
        return Math.max(..._arr);
    }

Upvotes: 0

You can use a reduce() function.

Example:

let obj = { "a": 4, "b": 0.5, "c": 0.35, "d": 5 }

let max = Object.entries(obj).reduce((max, entry) => entry[1] >= max[1] ? entry : max, [0, -Infinity])
let min = Object.entries(obj).reduce((min, entry) => entry[1] <= min[1] ? entry : min, [0, +Infinity])

console.log(max) // ["d", 5]
console.log(min) // ["c", 0.35]

Upvotes: 5

Timothy Bushell
Timothy Bushell

Reputation: 190

// Sorted
let Sorted = Object.entries({ "a":4, "b":0.5 , "c":0.35, "d":5 }).sort((prev, next) => prev[1] - next[1])
>> [ [ 'c', 0.35 ], [ 'b', 0.5 ], [ 'a', 4 ], [ 'd', 5 ] ]


//Min:
Sorted.shift()
>> [ 'c', 0.35 ]

// Max:
Sorted.pop()
>> [ 'd', 5 ]

Upvotes: 6

carlosfigueira
carlosfigueira

Reputation: 87228

There's no way to find the maximum / minimum in the general case without looping through all the n elements (if you go from, 1 to n-1, how do you know whether the element n isn't larger (or smaller) than the current max/min)?

You mentioned that the values change every couple of seconds. If you know exactly which values change, you can start with your previous max/min values, and only compare with the new ones, but even in this case, if one of the values which were modified was your old max/min, you may need to loop through them again.

Another alternative - again, only if the number of values which change are small - would be to store the values in a structure such as a tree or a heap, and as the new values arrive you'd insert (or update) them appropriately. But whether you can do that is not clear based on your question.

If you want to get the maximum / minimum element of a given list while looping through all elements, then you can use something like the snippet below, but you will not be able to do that without going through all of them

var list = { "a":4, "b":0.5 , "c":0.35, "d":5 };
var keys = Object.keys(list);
var min = list[keys[0]]; // ignoring case of empty list for conciseness
var max = list[keys[0]];
var i;

for (i = 1; i < keys.length; i++) {
    var value = list[keys[i]];
    if (value < min) min = value;
    if (value > max) max = value;
}

Upvotes: 24

Šime Vidas
Šime Vidas

Reputation: 185933

Update: Modern version (ES6+)

let obj = { a: 4, b: 0.5 , c: 0.35, d: 5 };

let arr = Object.values(obj);
let min = Math.min(...arr);
let max = Math.max(...arr);

console.log( `Min value: ${min}, max value: ${max}` );


Original Answer:

Try this:

let obj = { a: 4, b: 0.5 , c: 0.35, d: 5 };
var arr = Object.keys( obj ).map(function ( key ) { return obj[key]; });

and then:

var min = Math.min.apply( null, arr );
var max = Math.max.apply( null, arr );

Live demo: http://jsfiddle.net/7GCu7/1/

Upvotes: 202

user12723650
user12723650

Reputation: 21

var newObj = { a: 4, b: 0.5 , c: 0.35, d: 5 };
var maxValue = Math.max(...Object.values(newObj))
var minValue = Math.min(...Object.values(newObj))

Upvotes: 2

Neel Rathod
Neel Rathod

Reputation: 2111

You can also try with Object.values

const points = { Neel: 100, Veer: 89, Shubham: 78, Vikash: 67 };

const vals = Object.values(points);
const max = Math.max(...vals);
const min = Math.min(...vals);
console.log(max);
console.log(min);

Upvotes: 5

JBallin
JBallin

Reputation: 9787

Here's a solution that allows you to return the key as well and only does one loop. It sorts the Object's entries (by val) and then returns the first and last one.

Additionally, it returns the sorted Object which can replace the existing Object so that future sorts will be faster because it will already be semi-sorted = better than O(n). It's important to note that Objects retain their order in ES6.

const maxMinVal = (obj) => {
  const sortedEntriesByVal = Object.entries(obj).sort(([, v1], [, v2]) => v1 - v2);

  return {
    min: sortedEntriesByVal[0],
    max: sortedEntriesByVal[sortedEntriesByVal.length - 1],
    sortedObjByVal: sortedEntriesByVal.reduce((r, [k, v]) => ({ ...r, [k]: v }), {}),
  };
};

const obj = {
  a: 4, b: 0.5, c: 0.35, d: 5
};

console.log(maxMinVal(obj));

Upvotes: 3

Dave Kalu
Dave Kalu

Reputation: 1595

You could try:

const obj = { a: 4, b: 0.5 , c: 0.35, d: 5 };
const max = Math.max.apply(null, Object.values(obj));
console.log(max) // 5

Upvotes: 14

Sergey Zhigalov
Sergey Zhigalov

Reputation: 1219

Using the lodash library you can write shorter

_({ "a":4, "b":0.5 , "c":0.35, "d":5 }).values().max();

Upvotes: 3

Andrii Kudriavtsev
Andrii Kudriavtsev

Reputation: 1304

// 1. iterate through object values and get them
// 2. sort that array of values ascending or descending and take first, 
//    which is min or max accordingly
let obj = { 'a': 4, 'b': 0.5, 'c': 0.35, 'd': 5 }
let min = Object.values(obj).sort((prev, next) => prev - next)[0] // 0.35
let max = Object.values(obj).sort((prev, next) => next - prev)[0] // 5

Upvotes: 6

jaydip jadhav
jaydip jadhav

Reputation: 487

This works for me:

var object = { a: 4, b: 0.5 , c: 0.35, d: 5 };
// Take all value from the object into list
var valueList = $.map(object,function(v){
     return v;
});
var max = valueList.reduce(function(a, b) { return Math.max(a, b); });
var min = valueList.reduce(function(a, b) { return Math.min(a, b); });

Upvotes: 0

user4815162342
user4815162342

Reputation: 1688

For nested structures of different depth, i.e. {node: {leaf: 4}, leaf: 1}, this will work (using lodash or underscore):

function getMaxValue(d){
    if(typeof d === "number") {
        return d;
    } else if(typeof d === "object") {
        return _.max(_.map(_.keys(d), function(key) {
            return getMaxValue(d[key]);
        }));
    } else {
        return false;
    }
}

Upvotes: 2

Niet the Dark Absol
Niet the Dark Absol

Reputation: 324640

min and max have to loop through the input array anyway - how else would they find the biggest or smallest element?

So just a quick for..in loop will work just fine.

var min = Infinity, max = -Infinity, x;
for( x in input) {
    if( input[x] < min) min = input[x];
    if( input[x] > max) max = input[x];
}

Upvotes: 12

Related Questions