简体   繁体   中英

How to get the min, max, and sum of JSON data

I had JSON data that came back with single int values. With some changes, the values are now coming back as arrays of ints (as well as the original format).

{
  "value": 10,
  "value": 70,
  "value": 30,
  "value": 200
}

- and -

{
  "value": [64, 13, 55, 34, 52, 43, 59, 20, 20],
  "value": [10, 90, 20, 80, 30, 70, 60, 40, 50]
}

I had a formula that would return the min, max, and sum of the old version of JSON data. Now it doesn't work, and I can't figure out what would be the best way to re-write the function to handle the arrays. Or if its better to make a second function to handle just arrays and do a check if it is an int or array?

Is there a way that would return (from the numbers above):

// no value array, apply to all
[ 10, 200, 310 ] // min, max, sum

- and -

// for each of the value arrays
[ 23, 64, 360 ] // val 1 - min, max, sum
[ 10, 90, 450 ] // val 2 - min, max, sum

 // input data const value = document.querySelectorAll( "div" ).forEach( el => { const contents = el.textContent, // get the text in the <div> json = JSON.parse( contents ), // parse the data jsonData = json.data; // get the data only // normalise the data // @from: https://stackoverflow.com/a/67294607/1086990 const normaliseData = arr => { const data = arr.map(({ value }) => value); return typeof arr[0].value === 'number'? [data]: data; }; // add into const const valueArray = normaliseData( jsonData ); // get the min / max / sum const minMaxSum = valueArray.forEach( e => { return [ Math.min(...e), Math.max(...e), [...e].reduce((v, w) => v + w) ]; }); // output console.log( minMaxSum ); });
 <div> { "data": [ { "value": [64, 23, 45, 34, 52, 43, 59, 40] }, { "value": [10, 90, 20, 80, 30, 70, 60, 40, 50] } ] } </div> <div> { "data": [ { "value": 600 }, { "value": 70 }, { "value": 30 } ] } </div>

Normalize the data by testing the type of the value of the first object in each array:

const valueInArray = [{ value: [64, 23] }, { value: [45, 34] }];
const valueAsSingle = [{ value: 600 }, { value: 70 }];

const normalizeData = arr => {
  const data = arr.map(({ value }) => value);

  return typeof arr[0].value === 'number'
    ? [data]
    : data;
};

console.log(normalizeData(valueInArray));
//=> [ [ 64, 23 ], [ 45, 34 ] ]

console.log(normalizeData(valueAsSingle));
//=> [ [ 600, 70 ] ]

Now they are the same shape, and so you can treat them equally.

You can use Math.max and Math.min to find the maximum and minimum of the array then assign the values in the specific variables.

Currently, when you are using val.value it is consisting of the whole array and hence you also need to iterate over the array to find the max, min, or sum.

To find the sum use reduce on the val.value array and then add it in the acc[2] .

 // input data const valueInArray = document.getElementById("valueInArray").innerHTML, valueAsSingle = document.getElementById("valueAsSingle").innerHTML; // parse const jsonArray = JSON.parse( valueInArray ), jsonNumber = JSON.parse( valueAsSingle ), jsonArrayData = jsonArray.data, jsonNumberData = jsonNumber.data; // get numbers const minMaxSumArray = jsonArrayData.reduce( ( acc, val ) => { // smallest number acc[0] = ( ( acc[0] === undefined || Math.min(...val.value) < acc[0] )? Math.min(...val.value): acc[0] ) // largest number acc[1] = ( ( acc[1] === undefined || Math.max(...val.value) > acc[1] )? Math.max(...val.value): acc[1] ) // sum of numbers acc[2] = ( acc[2] === undefined? val.value.reduce((v, w) => v + w): val.value.reduce((v, w) => v + w) + acc[2] ) console.log('answer', acc) // return the array return acc; }, [] );
 <div id="valueInArray"> { "data": [ { "value": [64, 23, 45, 34, 52, 43, 59, 40] }, { "value": [10, 90, 20, 80, 30, 70, 60, 40, 50] } ] } </div> <div id="valueAsSingle"> { "data": [ { "value": 10 }, { "value": 70 }, { "value": 30 } ] } </div>

My take on it: first, create a single Array of all values (either arrays or single) by concatening them and using Array.flat() to flatten it. Then use a reducer to determine the sum and use Math.min/max for the min and max values.

 // input data const valuesInArray = JSON.parse( document.querySelector("#valueInArray").textContent).data; const singleValues = JSON.parse( document.querySelector("#valueAsSingle").textContent).data; // get all values from the objects to a single Array of values // (so: convert all to single values) const allValues = valuesInArray.map( v => v.value ).concat(singleValues.reduce( (acc, val) => [...acc, +val.value], [] ) ).flat(); // let's see what we have console.log(`All values from both objects: ${JSON.stringify(allValues)}`); // create sum, min and max const [ sum, min, max, ] = [ allValues.reduce( (a, v) => a + +v, 0), Math.min(...allValues), Math.max(...allValues) ]; console.log(`From all values sum is ${sum}, min ${min} and max ${max}`);
 div { display: none; }
 <div id="valueInArray"> { "data": [ { "value": [64, 23, 45, 34, 52, 43, 59, 40] }, { "value": [10, 90, 20, 80, 30, 70, 60, 40, 50] } ] } </div> <div id="valueAsSingle"> { "data": [ { "value": 10 }, { "value": 70 }, { "value": 30 } ] } </div>

The second snippet aggregates data per value, where the single values are added as a values array to valuesInArray .

 // input data const valuesInArray = JSON.parse( document.querySelector("#valueInArray").textContent).data; const singleValues = JSON.parse( document.querySelector("#valueAsSingle").textContent).data; // create sum, min and max *per value*, in one go const aggregatesAdded = valuesInArray.concat({ value: singleValues.reduce( (acc, val) => [...acc, +val.value], [] ) } ).reduce( (acc, val) => [...acc, {...val, aggregatedValues: { sum: val.value.reduce( (a, v) => a + +v, 0 ), min: Math.min(...val.value), max: Math.max(...val.value) } } ], []) document.querySelector("pre").textContent = JSON.stringify({data: aggregatesAdded}, null, 2);
 div { display: none; }
 <div id="valueInArray"> { "data": [ { "value": [64, 23, 45, 34, 52, 43, 59, 40] }, { "value": [10, 90, 20, 80, 30, 70, 60, 40, 50] } ] } </div> <div id="valueAsSingle"> { "data": [ { "value": 10 }, { "value": 70 }, { "value": 30 } ] } </div> <pre id="result"></pre>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM