【问题标题】:How to get the min, max, and sum of JSON data如何获取 JSON 数据的最小值、最大值和总和
【发布时间】:2021-07-20 13:24:36
【问题描述】:

我有返回单个 int 值的 JSON 数据。经过一些更改,这些值现在以整数数组(以及原始格式)的形式返回。

{
  "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]
}

我有一个公式可以返回旧版本 JSON 数据的最小值、最大值和总和。现在它不起作用,我不知道重写函数来处理数组的最佳方法是什么。或者如果创建第二个函数来处理数组并检查它是 int 还是数组更好?

有没有办法返回(从上面的数字):

// 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>

【问题讨论】:

  • 我猜你迷路了,因为你使用 reduce 里面有 20 行内容,而简单的 3 行循环也可以解决问题。
  • @georg 你如何将它简化为 3 行?

标签: javascript arrays


【解决方案1】:

通过测试每个数组中第一个对象的值的类型来规范化数据:

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 ] ]

现在它们是相同的形状,因此您可以平等对待它们。

【讨论】:

  • 感谢@Corey。正常化后我似乎仍然有问题。如果你看这里codepen.io/markbattistella/pen/jOyJRzG 所以第 25 和 29 行似乎没有返回 min/max/sum
  • @markb .forEach() 不返回数组。将其更改为 .map() 即可。
【解决方案2】:

您可以使用 Math.max 和 Math.min 找到数组的最大值和最小值,然后在特定变量中分配值。

目前,当您使用 val.value 时,它由整个数组组成,因此您还需要遍历数组以找到最大值、最小值或总和。

要查找总和,请在 val.value 数组上使用 reduce,然后将其添加到 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>

【讨论】:

  • 这似乎有效,但也许我在原始帖子中错过了它。它不处理这两种类型的值(单个整数超过许多 value 和数组整数)
【解决方案3】:

我对此的看法:首先,通过连接它们并使用 Array.flat() 将其展平,创建一个包含所有值(数组或单个)的单个数组。然后使用 reducer 确定总和并使用 Math.min/max 作为最小值和最大值。

// 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>

第二个 sn-p 聚合每个值的数据,其中单个值作为值数组添加到 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>

【讨论】:

  • 对数组进行排序以获得其最小值/最大值是浪费循环。
  • 好的,那么让我们使用 Math.min/max。虽然我怀疑 Math.min/max 也会循环,但据说更优化。 See the V8 code
  • @KooiInc 在不合并所有数字的情况下,我将如何使用它来仅处理单个 data 字符串?因此,如果值以valueInArray 格式传递,它将获得每个值数组的最小值、最大值和总和。如果值作为valueAsSingle 传递,它将得到所有单个整数的最小值、最大值和总和
  • @markb 也许第二个 sn-p 可以帮助你?
  • @KooiInc 确实如此,只是您仍在合并所有值。我正在尝试按 json 隔离它们 - codepen.io/markbattistella/pen/jOyJRzG。我想传递任何一种类型,它都适用
猜你喜欢
  • 2019-08-03
  • 2018-10-30
  • 1970-01-01
  • 2020-08-16
  • 2019-05-08
  • 2019-06-24
  • 1970-01-01
  • 2014-11-20
  • 2021-08-01
相关资源
最近更新 更多