cqwcns 发表于 2022-10-16 12:42

JS,数组对象统计的方法(最大值、最小值、平均值)

最近强迫症越来越严重,已经忘记了“能跑就行”的原则,总是追求改进,折腾自己。


现在我们有一组数据,需求是对列进行计算,并添加两行,分别是最大值、最小值。
通过以下方法,功能已经实现。
但还是感觉代码太冗长,不利于维护和复用。
请各位大佬指教,有没有更简洁,和方便复用的写法,例如要增加最大值、最小值、平均值三行。有什么好的实现方法,欢迎交流、指正。感谢。



<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>

      // 原数据
      const arrData = [
            {
                "col0": "2022/10/5",
                "col1": 0.80,
                "col2": 0.92,
                "col3": 0.33
            }, {
                "col0": "2022/10/6",
                "col1": 0.86,
                "col2": 0.63,
                "col3": 0.68
            }, {
                "col0": "2022/10/7",
                "col1": 0.83,
                "col2": 0.89,
                "col3": 0.62
            }
      ];
      // 先打印看看原数据
      console.table(arrData);

      // 获得对象的key
      const arrKeys = Object.keys(arrData);


      // =====最大值=====
      // 获得最大值(数组)
      let arrMax = arrKeys.map((key, index) => {
            let arr = [];
            arrData.forEach(row => {
                arr.push(row)
            });
            return index ? Math.max(...arr) : '最大值'
      });

      // 转回对象
      let objMax = {};
      arrKeys.forEach((key, index) => {
            objMax = arrMax
      });
      // 添加到原数据中
      arrData.push(objMax)

      // =====最小值=====
      // 获得最小值(数组)
      let arrMin = arrKeys.map((key, index) => {
            let arr = [];
            arrData.forEach(row => {
                arr.push(row)
            });
            return index ? Math.min(...arr) : '最大值'
      });

      // 转回对象
      let objMin = {};
      arrKeys.forEach((key, index) => {
            objMin = arrMin
      });
      // 添加到原数据中
      arrData.push(objMin)

      // 打印结果
      console.table(arrData);

    </script>
</body>

</html>

甜萝 发表于 2022-10-16 13:03

我也有点强迫症 好烦 {:301_973:}{:301_980:}{:301_972:}

ligxi 发表于 2022-10-16 14:16

凡是有重复出现的代码,就把这段代码提取成一个函数,给出不同的参数,从而得到不同的结果。

wan1330 发表于 2022-10-16 14:45

// 最大值
const maxValue = arrData.reduce((preValue, current) => Math.max(preValue, current.col1).toFixed(2), 0)
// 最小值
const minValue = arrData.reduce((preValue, current) => Math.min(preValue, current.col1).toFixed(2), 1)
// 求和以col1为例
const countCol1 = arrData.reduce((preValue, current) => preValue += current.col1,0)

cqwcns 发表于 2022-10-16 21:58

自己研究了一下,好像这个比较符合自己的需求。


      // 最大值
      const maxValue = (arr) => {
            // 首先根据数组的第一个对象,生成一个空的对象
            let obj = { ...arr };
            Object.keys(arr).forEach((key, index) => {
                obj = index ? '' : '最大值'
            });

            // 通过累加器返回最大值
            return arr.reduce((pre, cur) => {
                for (const key in pre) {
                  pre = pre && typeof pre === "number" ? Math.max(pre, cur) : pre ? pre : cur
                }
                return pre
            }, obj)
      }

      console.log('maxValue', maxValue(arrData))
      // {col0: '最大值', col1: 0.86, col2: 0.92, col3: 0.68}

cqwcns 发表于 2022-10-16 22:19

稍微修改了以下,支持数组对象直接添加最大值、最小值的行。

// 原数据
      const arrData = [
            {
                "col0": "2022/10/5",
                "col1": 0.80,
                "col2": 0.92,
                "col3": 0.33
            }, {
                "col0": "2022/10/6",
                "col1": 0.86,
                "col2": 0.63,
                "col3": 0.68
            }, {
                "col0": "2022/10/7",
                "col1": 0.83,
                "col2": 0.89,
                "col3": 0.62
            }
      ];
      // 先打印看看原数据
      console.table(arrData);

      // 获得最大值或最小值
      const pushMaxOrMin = (arr,isMax) => {
            // 首先根据数组的第一个对象,生成一个空的对象
            const obj = { ...arr };
            Object.keys(arr).forEach((key, index) => {
                obj = index ? '' : isMax?'最大值':'最小值'
            });

            // 通过累加器计算
            const res = arr.reduce((pre, cur) => {
                for (const key in pre) {
                  pre = pre && typeof pre === "number" ? isMax?Math.max(pre, cur):Math.min(pre, cur) : pre ? pre : cur
                }
                return pre
            }, obj)

            // 添加到原数组
            arr.push(res)

      }

      // 添加最大值行
      pushMaxOrMin(arrData,1)
      // 添加最小值行
      pushMaxOrMin(arrData,0)
      console.table(arrData)

Dropless 发表于 2022-10-17 01:00

我觉得从最大值, 最小值等等方法剥离出来一个抽象的逻辑要好一点, 你这个一堆三元运算符挤在一起看着不头疼吗? 我反正是看都不愿看.

既然是对列作运算, 我的思路是先写一个列选择器, 返回指定列的数据, 这样不仅是求最大值, 求最小值, 以后要是有新的计算, 比如求平均值等等, 这个都可以复用.
// 原数据
const arrData = [
    {
      "col0": "2022/10/5",
      "col1": 0.80,
      "col2": 0.92,
      "col3": 0.33
    }, {
      "col0": "2022/10/6",
      "col1": 0.86,
      "col2": 0.63,
      "col3": 0.68
    }, {
      "col0": "2022/10/7",
      "col1": 0.83,
      "col2": 0.89,
      "col3": 0.62
    }
];


const memo = {}; // 存放已经选择过的列, 再次选择同样的列时不用再跑循环, 直接查
let selectCol = (data, colKey) => {
    if (memo) return memo;
    let col = [];
    data.forEach( element => {
      col.push(element);
    })
    memo = col;
    return col;
}

// 获得对象的key
const colKeys = Object.keys(arrData);

let maxRow = {}, minRow = {};
colKeys.forEach( (colKey, index) => {
    if (!index) {
      maxRow = "最大值";
      minRow = "最小值";
    }
    else {
      maxRow = Math.max(...selectCol(arrData, colKey));
      minRow = Math.min(...selectCol(arrData, colKey));
    }
})

console.table([...arrData, maxRow, minRow]);

页: [1]
查看完整版本: JS,数组对象统计的方法(最大值、最小值、平均值)