Finding the max value of an attribute in an array of objects in an object

Viewed 416

I have a JavaScript object and want to get the highest value of all entries. I have tried this:

d = {
"A": [ {"value": 10}, {"value": 20}, {"value": 30} ],
"B": [ {"value": 50}, {"value": 60}, {"value": 1000} ],
}

Object.keys(d).map(
    function(k) { 
        Math.max.apply(Math, d[k].map(
            function(e) {
                console.log(value);
            }
        ))
    }
) 

The result should be 1000.

9 Answers

You can use spread syntax ... in Math.max after you map and flatten the array.

const d = {
  "A": [ {"value": 10}, {"value": 20}, {"value": 30} ],
  "B": [ {"value": 50}, {"value": 60}, {"value": 1000} ],
}

const max = Math.max(...[].concat(...Object.values(d)).map(({value}) => value))
console.log(max)

Use Object.values, flatMap and Math.max with spreading.

const d = {"A":[{"value":10},{"value":20},{"value":30}],"B":[{"value":50},{"value":60},{"value":1000}]};
const res = Math.max(...Object.values(d).flat().flatMap(Object.values));
console.log(res);

Because flat isn't well supported (and neither is flatMap) you can use reduce as well.

const d = {"A":[{"value":10},{"value":20},{"value":30}],"B":[{"value":50},{"value":60},{"value":1000}]};
const res = Math.max(...Object.values(d).map(e => e.map(Object.values)).reduce((a, c) => [].concat(...a, ...c)));
console.log(res);

If you want es5 code, try this:

var d = {
"A": [ {"value": 10}, {"value": 20}, {"value": 30} ],
"B": [ {"value": 50}, {"value": 60}, {"value": 1000} ],
};

var results = [];
for(var key in d)
{
    d[key].forEach(function (obj){
        results.push(obj.value);
    });
}
console.log(Math.max.apply(null, results));

Try something like this by flattening the values first then sorting it in ascending order and taking the last element out of the sorted array:

const data = {
  "A": [ {"value": 10}, {"value": 20}, {"value": 30 } ],
  "B": [ {"value": 50}, {"value": 60}, {"value": 1000} ],
};


const highestValue = Object.values(data)
.flatMap(x => x)
.sort((a, b) => a.value - b.value)
.slice(-1);

console.log(highestValue);

d = {
    "A": [{ "value": 10 }, { "value": 20 }, { "value": 30 }],
    "B": [{ "value": 50 }, { "value": 60 }, { "value": 1000 }],
}


var maxValue = Math.max.apply(null,Object.keys(d).map(key => Math.max.apply(null,d[key].map(x => x.value))));

console.log(maxValue);

You can use a good old loop

let d = {
"A": [ {"value": 10}, {"value": 20}, {"value": 30} ],
"B": [ {"value": 50}, {"value": 60}, {"value": 1000} ],
}

let maxValue;
for (let key in d)
{
  for (let i = 0, len = d[key].length; i < len; ++i)
  {
    if (maxValue === undefined || maxValue < d[key][i].value)
      maxValue = d[key][i].value;
  }
}

console.log(maxValue);

Since neither Array.flat nor Array.flatMap are well supported without polyfill here is a solution with Array.reduce, Object.values and Array.map:

const d = {
"A": [ {"value": 10}, {"value": 20}, {"value": 30} ],
"B": [ {"value": 50}, {"value": 60}, {"value": 1000} ],
}

let r = Math.max(...Object.values(d).reduce((r,c)=>[...r,...c]).map(x => x.value))

console.log(r)

The idea is to use Object.values to get straight to the values of the object. Then use Array.reduce for the flattening of the arrays and Array.map to extract the value. Then spread to Math.max for the final result.

For actual JSON string, it can be done during parsing :

var max = -Infinity, json = '{"A":[{"value":10},{"value":20},{"value":30}],"B":[{"value":50},{"value":60},{"value":1000}]}'

JSON.parse(json, (k, v) => max = v > max ? v : max)

console.log( max )

For JavaScript object :

const d = { "A": [ {"value": 10}, {"value": 20}, {"value":   30 } ],
            "B": [ {"value": 50}, {"value": 60}, {"value": 1000 } ] }

console.log( Math.max(...Object.values(d).flat().map(x => x.value)) )

Only simply using map and reduce and chaining them together can give you the desired max value. I have used underscore js though, you can use simple map and reduce methods for the same.

var d = {
     "A": [ {"value": 10}, {"value": 20}, {"value": 30} ],
     "B": [ {"value": 50}, {"value": 60}, {"value": 1000} ],
     "C": [ {"value": 30}, {"value": 90}, {"value": 300} ],
     }

var maxvalue = _.reduce(_.map(d,(items)=>{  
    return _.reduce(items , (p,i)=>{
            return p> i.value ? p: i.value;
        },0)
}) , (maxy, iter)=>{
    return maxy > iter ? maxy: iter;
},0);
Related