一、 别再用循环当人工计数器了!
那天我同事小王,盯着屏幕念念有词:“一、二、三……” 我探头一看,好家伙,他正用for循环数PHP数组有几个元素!我当场笑喷:“兄弟,你是人类计算器成精吗?”
其实90%的新手都干过这事——不是手动$i++,就是在日记本上画正字。但PHP早就给你备好了超级加速器:count()函数。这玩意儿就像超市结账时的扫码枪,“嘀”一声,管你购物车里丢了多少商品,总价瞬间出来。
二、 count()到底是个什么鬼?
官方说法枯燥得像说明书,咱们来点人话版:
count(array,mode) 就干两件事:
- 数你数组里有多少个元素(默认模式)
- 加个神秘参数,就能连子孙后代一起数(递归模式)
举个栗子🌰:
$零食柜 = ['薯片', '可乐', '巧克力', '瓜子'];
echo count($零食柜); // 输出:4
就这?对,就这么简单!但如果你以为它只会数零食,那就太小看它了。
三、 二维数组?多维迷宫?照数不误!
最近做抽奖系统,遇到个经典场景:
$部门员工 = [
'技术部' => ['张三', '李四', '王五'],
'市场部' => ['赵六', '钱七'],
'人事部' => ['孙八']
];
新手噩梦题:公司总共多少人?
菜鸟可能嵌套循环,老鸟直接:
$总人数 = 0;
foreach($部门员工 as $部门){
$总人数 += count($部门);
}
但终极解法更骚:
$总人数 = count($部门员工, COUNT_RECURSIVE) - count($部门员工);
// 输出:6
这里用了COUNT_RECURSIVE模式,它会像扫雷游戏一样,把嵌套数组全部展开数一遍。不过注意:它会把父数组也算作一个元素,所以要减去部门数量。
四、 sizeof():count()的双胞胎兄弟?
很多教程会说“sizeof()是count()的别名”,但!这里有个冷知识:
在远古PHP版本中,sizeof()在某些边缘场景有微妙差异。虽然现在99.9%情况通用,但:
- 写
count()显得你很专业 - 团队协作时统一用count避免困惑
- 面试时能装X:“我通常用count,因为sizeof可能让人误以为是取内存大小”
五、 空数组、null、未定义变量的修罗场
这才是翻车高发区!看这段夺命代码:
$未初始化数组;
echo count($未初始化数组); // 警告+返回0?不!是警告+返回1!
防翻车守则:
- 先用
isset()检查变量是否存在 - 用
is_array()确认它真是数组 - 安全写法模板:
$人数 = is_array($员工列表) ? count($员工列表) : 0;
六、 实战篇:统计函数玩出花的7个场景
场景1:烧烤店库存预警系统
$库存 = [
'羊肉串' => 150,
'鸡翅' => 30, // 低于警戒线!
'馒头片' => 200
];
$低库存商品 = [];
foreach($库存 as $商品 => $数量){
if($数量 < 50){
$低库存商品[] = $商品;
}
}
echo "急需补货的有:" . implode('、', $低库存商品);
echo "共" . count($低库存商品) . "种商品";
场景2:投票系统去重统计
$投票记录 = ['张三', '李四', '张三', '王五', '李四'];
$有效票数 = count(array_unique($投票记录)); // 先去重再统计!
echo "有效票数:$有效票数"; // 输出:3
场景3:动态生成分页按钮
$所有文章 = [...]; // 假设100篇文章
$每页显示 = 10;
$总页数 = ceil(count($所有文章) / $每页显示); // ceil()向上取整
// 生成分页按钮
for($i = 1; $i <= $总页数; $i++){
echo "<button>第{$i}页</button> ";
}
七、 性能暗战:count()的隐藏属性
有个江湖传说:“count()很耗性能”。实测打脸:
- count()是O(1)时间复杂度,因为PHP数组内部维护了长度计数器
- 但!在循环里每次都count()就是作死:
// 糟糕写法
for($i = 0; $i < count($巨大数组); $i++){
// 每次循环都数一遍,CPU在哭泣
}
// 优雅写法
$总数 = count($巨大数组);
for($i = 0; $i < $总数; $i++){
// 只数一次,CPU爱你
}
八、 扩展包:那些冷门但好用的统计函数
1. array_count_values() —— 统计值出现的次数
$考试成绩 = [85, 90, 85, 78, 90, 90];
$分数分布 = array_count_values($考试成绩);
print_r($分数分布);
/* 输出:
[
85 => 2,
90 => 3,
78 => 1
]
*/
2. 统计二维数组某列的和
$订单明细 = [
['商品' => '手机', '数量' => 2],
['商品' => '耳机', '数量' => 5],
['商品' => '贴膜', '数量' => 10]
];
$总数量 = array_sum(array_column($订单明细, '数量'));
echo "总销量:$总数量"; // 输出:17
九、 完整实战:班级成绩分析系统
下面这个例子,囊括了今天所有知识点:
<?php
/**
* 班级成绩分析系统 - 统计函数实战
*/
class 成绩分析器 {
private $学生数据;
public function __construct($数据) {
$this->学生数据 = $数据;
}
// 1. 基础统计
public function 获取总人数() {
return count($this->学生数据);
}
// 2. 统计各分数段人数
public function 分数段分析() {
$分段 = ['优秀' => 0, '良好' => 0, '及格' => 0, '不及格' => 0];
foreach($this->学生数据 as $学生) {
$分数 = $学生['分数'];
if($分数 >= 90) $分段['优秀']++;
elseif($分数 >= 80) $分段['良好']++;
elseif($分数 >= 60) $分段['及格']++;
else $分段['不及格']++;
}
return $分段;
}
// 3. 统计缺考人数
public function 统计缺考() {
$缺考名单 = [];
foreach($this->学生数据 as $学号 => $学生) {
if($学生['缺考']) {
$缺考名单[] = $学生['姓名'];
}
}
return [
'人数' => count($缺考名单),
'名单' => $缺考名单
];
}
// 4. 生成统计报告
public function 生成报告() {
$报告 = "==== 成绩分析报告 ====\n";
$报告 .= "总人数:" . $this->获取总人数() . "\n";
$分段 = $this->分数段分析();
$报告 .= "\n【分数段分布】\n";
foreach($分段 as $段名 => $人数) {
$百分比 = round($人数 / $this->获取总人数() * 100, 2);
$报告 .= "{$段名}:{$人数}人 ({$百分比}%)\n";
}
$缺考 = $this->统计缺考();
$报告 .= "\n【缺考统计】\n";
$报告 .= "缺考人数:" . $缺考['人数'] . "\n";
if($缺考['人数'] > 0) {
$报告 .= "缺考名单:" . implode('、', $缺考['名单']) . "\n";
}
return $报告;
}
}
// ====== 实战数据 ======
$班级数据 = [
'001' => ['姓名' => '张三', '分数' => 95, '缺考' => false],
'002' => ['姓名' => '李四', '分数' => 78, '缺考' => false],
'003' => ['姓名' => '王五', '分数' => 88, '缺考' => false],
'004' => ['姓名' => '赵六', '分数' => 55, '缺考' => false],
'005' => ['姓名' => '钱七', '分数' => 92, '缺考' => false],
'006' => ['姓名' => '孙八', '分数' => 0, '缺考' => true], // 缺考
'007' => ['姓名' => '周九', '分数' => 61, '缺考' => false],
'008' => ['姓名' => '吴十', '分数' => 84, '缺考' => false],
'009' => ['姓名' => '郑十一', '分数' => 0, '缺考' => true], // 缺考
];
// 运行分析
$分析器 = new 成绩分析器($班级数据);
echo $分析器->生成报告();
// ====== 额外技巧:快速统计 ======
echo "\n【快速统计技巧演示】\n";
// 技巧1:使用array_column提取分数列
$所有分数 = array_column($班级数据, '分数');
echo "平均分:" . array_sum($所有分数) / count($所有分数) . "\n";
// 技巧2:筛选及格人数(使用array_filter)
$及格人数 = count(array_filter($所有分数, function($分数) {
return $分数 >= 60;
}));
echo "及格人数:{$及格人数}\n";
// 技巧3:最高分/最低分(排除0分缺考)
$有效分数 = array_filter($所有分数, function($分数) {
return $分数 > 0;
});
echo "最高分:" . max($有效分数) . ",最低分:" . min($有效分数) . "\n";
?>
十、 常见坑爹问题排查指南
Q1:为什么count()返回1,我的数组明明是空的?
A:大概率你数的是null或者没初始化。先var_dump()看看变量真身。
Q2:递归模式把我搞晕了,有简单理解方式吗?
A:想象成拆快递——普通模式只数外箱,递归模式会把箱子里的每个小包装都数一遍。
Q3:超大数组统计会不会内存爆炸?
A:count()只读取数组头信息,不遍历内容,所以就算数组有100万元素,它也是瞬间完成。
十一、 升级思维:统计是为了什么?
最后升华一下:数数组不是目的,通过数据驱动决策才是。比如:
- 统计商品销量 → 决定下个月进货量
- 统计用户停留时长 → 优化页面设计
- 统计API调用频率 → 优化服务器配置
记住这个心法:统计是眼睛,决策是大脑,代码是手脚。三者配合,你写的就不再是代码,而是商业解决方案。
彩蛋:测试题——下面代码输出什么?
$谜之数组 = [1, 2, [3, 4, [5]], 6];
echo count($谜之数组, COUNT_RECURSIVE);
想不出来?亲自跑一遍吧!编程最爽的时刻,不就是“啊哈,原来如此”的顿悟瞬间吗?
1万+

被折叠的 条评论
为什么被折叠?



