Laravel Collections如何优雅统计指定元素在另一集合的出现次数
适配该场景的Laravel集合实现方案
核心思路
你一开始想的嵌套循环写法虽然能跑通,但完全没必要费那劲——Laravel集合自带专门算元素出现次数的countBy()方法,根本不用自己写计数器和一堆if判断,两步就能搞定,代码短还比嵌套循环快:
- 先把
$skills集合过一遍,算出每个技能出现了多少次,存成「技能名 => 出现次数」的对应表 - 顺着
$req的顺序,从刚才的对应表里直接拿数就行,匹配不到的技能默认算0
可直接抄的代码
// 1. 一次性统计完所有技能的出现频次 $skillCountMap = $skills->countBy(); // 2. 按$req的顺序生成统计结果 $finalStat = $req->mapWithKeys(function ($requirement) use ($skillCountMap) { // 从映射里取数,找不到的话默认返回0 return [$requirement => $skillCountMap->get($requirement, 0)]; });
跑出来的结果完全和你预期的一样:
// $finalStat的实际结构 collect([ 'Installation' => 2, 'Konfiguration' => 2, 'Automatisierung' => 4 ]);
如果要拼成你提到的那种自然语言输出,直接在后面加链式调用就行:
$outputText = $finalStat ->map(fn($count, $name) => "{$name} 出现{$count}次") ->implode('、'); // 最终输出文本:Installation 出现2次、Konfiguration 出现2次、Automatisierung 出现4次
为啥比你原来的写法好
- 没有冗余代码:不用写嵌套循环、不用自己累加计数、不用写条件判断,统计逻辑全是集合内部实现的
- 跑的更快:原来的嵌套循环是每核对一个任职要求,就把所有技能遍历一遍,技能多了会越来越慢;现在的写法是先把技能的计数一次性算完,后面取数都是直接查映射,效率高很多
- 自动满足要求:不在
$req范围内的技能(比如例子里的Engineering Team、Security)会被自动忽略,根本不会进到结果里 - 灵活度够:如果某个任职要求在技能里完全没出现,给
get()传个默认值0就行,不用额外写判断
小提示:你之前试的
contains()方法只能判断元素在不在,没法数次数,这个场景下核心要用的方法就是countBy(),完全不用自己实现统计逻辑。
内容的提问来源于stack exchange,提问作者Rabik
相关产品推荐
相关产品推荐

