With an object array that looks like this:
[{
"202201": {
"WO": 900,
"WS": 0,
"SY": 0.915,
"LY": 0.98,
"CT": 75
},
"202202": {
"WO": 300,
"WS": 0,
"SY": 0.915,
"LY": 0.98,
"CT": 73
},
"202203": {
"WO": 350,
"WS": 0,
"SY": 0.915,
"LY": 0.98,
"CT": 68
},
"202204": {
"WO": 400,
"WS": 0,
"SY": 0.915,
"LY": 0.98,
"CT": 77
},
"202205": {
"WO": 300,
"WS": 0,
"SY": 0.915,
"LY": 0.98,
"CT": 67
},
"Product": "A",
"Facility": "a-Facility"
},
{
"202201": {
"WO": 6665,
"WS": 0,
"SY": 0.903,
"LY": 0.993,
"CT": 73
},
"202202": {
"WO": 5907,
"WS": 0,
"SY": 0.903,
"LY": 0.993,
"CT": 71
},
"202203": {
"WO": 5893,
"WS": 0,
"SY": 0.903,
"LY": 0.993,
"CT": 74
},
"202204": {
"WO": 5486,
"WS": 0,
"SY": 0.903,
"LY": 0.993,
"CT": 67
},
"202205": {
"WO": 5448,
"WS": 0,
"SY": 0.903,
"LY": 0.993,
"CT": 69
},
"Product": "B",
"Facility": "b-Facility"
}]
I am attempting to find the maximum "CT" (or cycle time) for all products on a production line across all facilities. In the example above, it would be 77.
The closest (and most modern) example I can find that comes close looks like this:Math.max(...array.map(o => o.y))
and comes from this question about the max in an array of objects, but doesn't quite get into an array of objects and all numeric properties of each object.
I assume there's a way to map, not only the array of objects, but the object properties which have a property of "CT" (and replace "undefined" with 0) in order to arrive at the max of 77. I will continue investigating as I wait for support.
It's a typescript application, but a javascript answer will work for me, too.
PROGRESS:
I am also hoping for something more sophisticated than a double for loop, so if you can beat these options, I'll be super happy with it:
numbers = [];
data.forEach(d => {
numbers = numbers.concat(Object.keys(d).map(p => d[p].CT ? d[p].CT : 0));
})
maxCycle = Math.max(...numbers);
data.forEach(d => {
for (const w in d) {
maxCycle = maxCycle < d[w]['CT'] ? d[w]['CT'] : maxCycle;
}
});
CodePudding user response:
const maxValue = data.reduce((acc, current) => {
for(item of Object.values(current)) {
if(typeof(item) === 'object') {
for(key in item) if(key === 'CT' && item[key] > acc) acc = item[key];
}
}
return acc;
}, 0);
The short version of this one is
const maxValue = data.reduce((acc, dataItem) => {
for(item of Object.values(dataItem)) if(typeof(item) === 'object') for(key in item) if(key === 'CT' && item[key] > acc) acc = item[key];
return acc;
}, 0);
[Updated] More Optimized version
const maxValue = data.reduce((acc, current) => {
for(item of Object.values(current)) if(item['CT'] > acc) acc = item['CT'];
return acc;
}, 0);
Hope this helps!
CodePudding user response:
You can use Array.flatMap and then take a max out of it.
This is a oneliner that should work:
Math.max(...arr.flatMap(i => Object.values(i)).flatMap(obj => obj.CT || -Infinity))
We need 2 flatMap
as first we're taking the values of the objects and then we access the CT
property of those objects.
Also -Infinity
is a better option than 0, as you may have only negative values.
const arr = [{
"202201": {
"WO": 900,
"WS": 0,
"SY": 0.915,
"LY": 0.98,
"CT": 75
},
"202202": {
"WO": 300,
"WS": 0,
"SY": 0.915,
"LY": 0.98,
"CT": 73
},
"202203": {
"WO": 350,
"WS": 0,
"SY": 0.915,
"LY": 0.98,
"CT": 68
},
"202204": {
"WO": 400,
"WS": 0,
"SY": 0.915,
"LY": 0.98,
"CT": 77
},
"202205": {
"WO": 300,
"WS": 0,
"SY": 0.915,
"LY": 0.98,
"CT": 67
},
"Product": "A",
"Facility": "a-Facility"
},
{
"202201": {
"WO": 6665,
"WS": 0,
"SY": 0.903,
"LY": 0.993,
"CT": 73
},
"202202": {
"WO": 5907,
"WS": 0,
"SY": 0.903,
"LY": 0.993,
"CT": 71
},
"202203": {
"WO": 5893,
"WS": 0,
"SY": 0.903,
"LY": 0.993,
"CT": 74
},
"202204": {
"WO": 5486,
"WS": 0,
"SY": 0.903,
"LY": 0.993,
"CT": 67
},
"202205": {
"WO": 5448,
"WS": 0,
"SY": 0.903,
"LY": 0.993,
"CT": 69
},
"Product": "B",
"Facility": "b-Facility"
}
]
console.log(Math.max(...arr.flatMap(i => Object.values(i)).flatMap(obj => obj.CT || -Infinity)))