Javascript实现封装统计函数及代码优化

Javascript 实现封装统计函数及代码优化

需求:

Javascript 实现封装统计函数,想对下面数据按以下需求进行统计:


var persons = [
  { name: '郭靖', sex: '男', age: 25 },
  { name: '黄蓉', sex: '女', age: 25 },
  { name: '杨过', sex: '男', age: 15 },
  { name: '小龙女', sex: '女', age: 15 },
  { name: '张无忌', sex: '男', age: 21 },
  { name: '赵敏', sex: '女', age: 21 },
  { name: '周芷若', sex: '女', age: 21 },
  { name: '段誉', sex: '男', age: 20 },
  { name: '王语嫣', sex: '女', age: 20 },
  { name: '乔峰', sex: '男', age: 20 },
  { name: '阿紫', sex: '女', age: 20 },
  { name: '令狐冲', sex: '男', age: 16 },
  { name: '任盈盈', sex: '女', age: 16 }
];

 

1、按性别(sex)来统计人数
2、按年龄(age)来统计人数
3、按年龄(age)段来统计人数

实现

简单处理(未封装函数)


const result = [];
for (let i = 0; i < persons.length; i++) { 
    const item = persons[i];
    const key = item.sex;
    if (!result[key]) {
        result[key] = 0;
    }
    result[key]++;
}
console.log(result);
// 结果打印
// [男: 8, 女: 5]

为了能够支持任意字段都可以实现统计,可以根据上述代码封装成统计函数:


var countby = function (arr, key_field) {
    const result = [];
    for (let i = 0; i < arr.length; i++) { 
        const item = arr[i];
        const key = item[key_field];
        if (!result[key]) {
            result[key] = 0;
        }
        result[key]++;
    }
    return result;
}
console.log(countby(persons,'sex'));
// 结果打印
// [男: 8, 女: 5]

console.log(countby(persons,'age'));
// 结果打印
// [15: 2,16: 2,20: 4,21: 3,25: 2]


为了能够支持年龄段来统计,即:需要考虑如何获取代码的中 result[key]的 key,我们可以把获取 key 的方法开放出去。

改造 countby 函数:


var countby = function (arr, key_fun) {
    const result = [];
    for (let i = 0; i < arr.length; i++) { 
        const item = arr[i];
        const key = key_fun(item, i, arr);
        if (!result[key]) {
            result[key] = 0;
        }
        result[key]++;
    }
    return result;
}


console.log(countby(persons,f=>f.sex));
// 结果打印
// [男: 8, 女: 5]

console.log(countby(persons,f=>f.age));
// 结果打印
// [15: 2,16: 2,20: 4,21: 3,25: 2]

console.log(countby(persons,f=>f.age>=18?"成年人":"未成年人"));
// 结果打印
// [成年人: 9, 未成年人: 4]

优化分析封装统计函数的代码

目前封装的统计函数方法(countby)以及得出的结果数据已经很接近目标了,但目前 有几个关键问题,我们来 彻底优化并修正,让它:

正确统计人数(按任意字段)

返回 紧凑对象,而不是稀疏数组

性能更好、代码更简洁

支持链式调用和现代 JS 语法

问题分析:


const result = []; // 错误:用数组当 map
result[key] = 0;   // key 可能是字符串,会变成索引!

例如:key = '男' → result['男'] → result[NaN] → 错乱!

优化目标:

改用 Object 存储结果

支持按 sex, age, name 等任意字段计数

返回清晰对象 { 男: 8, 女: 5 }

代码简洁、高效、可读

优化版本(推荐)


const countby = (arr, key_fun) => {
  const result = {};
  for (const item of arr) {
    const key = key_fun(item);
    result[key] = (result[key] || 0) + 1;
  }
  return result;
};

更现代一行版(函数式,用到 reduce)


const countby = (arr, key_fun) =>
  arr.reduce((acc, item) => {
    const key = key_fun(item);
    acc[key] = (acc[key] || 0) + 1;
    return acc;
  }, {});

 

最终推荐代码(完整可运行)



var persons = [
  { name: '郭靖', sex: '男', age: 25 },
  { name: '黄蓉', sex: '女', age: 25 },
  { name: '杨过', sex: '男', age: 15 },
  { name: '小龙女', sex: '女', age: 15 },
  { name: '张无忌', sex: '男', age: 21 },
  { name: '赵敏', sex: '女', age: 21 },
  { name: '周芷若', sex: '女', age: 21 },
  { name: '段誉', sex: '男', age: 20 },
  { name: '王语嫣', sex: '女', age: 20 },
  { name: '乔峰', sex: '男', age: 20 },
  { name: '阿紫', sex: '女', age: 20 },
  { name: '令狐冲', sex: '男', age: 16 },
  { name: '任盈盈', sex: '女', age: 16 }
];
const countby = (arr, key_fun) => {
  const result = {};
  for (const item of arr) {
    const key = key_fun(item);
    result[key] = (result[key] || 0) + 1;
  }
  return result;
};
// 测试
console.log('按性别:', countby(persons, f => f.sex));
console.log('按年龄:', countby(persons, f => f.age));
console.log('按成年:', countby(persons, f => f.age >= 18 ? '成年人' : '未成年人'));

打印结果


// 打印结果
按性别:[男: 8, 女: 5]
按年龄:[15: 2,16: 2,20: 4,21: 3,25: 2]
按成年:[成年人: 9, 未成年人: 4]
© 版权声明

☆ END ☆
喜欢就点个赞吧
点赞0 分享
评论 抢沙发
  • 武穆逸仙

    昵称

  • 取消回复

    请填写用户信息:

图片正在生成中,请稍后...