
需求:
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]
© 版权声明
博主的文章没有高度、深度和广度,只是凑字数。利用读书、参考、引用、抄袭、复制和粘贴等多种方式打造成自己的纯镀 24k 文章!如若有侵权,请联系博主删除。
喜欢就点个赞吧





