
本文介绍一种使用 PHP 的 array_filter 结合字母频次统计(array_count_values)来严格筛选单词的方法:仅保留由给定字母集合构成、且各字母出现次数不超过原始字母数组中对应频次的单词。
本文介绍一种使用 php 的 `array_filter` 结合字母频次统计(`array_count_values`)来严格筛选单词的方法:仅保留由给定字母集合构成、且各字母出现次数不超过原始字母数组中对应频次的单词。
在实际开发中,常需根据一组“可用字母”(含重复)对单词列表进行精准过滤——不仅要求单词中每个字符都必须来自该字母池,还要求每个字符的出现频次不得超过池中对应字符的数量。例如,给定字母数组 ['a','c','r','r'](即最多允许 1 个 'a'、1 个 'c'、2 个 'r'),单词 'aa'(含 2 个 'a')和 'abc'(含未授权字符 'b')应被排除,而 'rr' 和 'carr' 则合法。
实现的关键在于双向频次比对:
- 使用
array_count_values($letters)构建基准字母频次表; - 对每个待检单词,用
mb_str_split($word)安全拆分为字符数组(兼容多字节字符,如中文或带重音符号的字母),再用array_count_values()统计其内部字符频次; - 遍历单词的字符频次表,逐项校验:若某字符不在基准表中,或其频次超过基准值,则立即拒绝该单词。
以下是完整可运行代码:
$letters = ['a', 'c', 'r', 'r'];
$words = ['carr', 'car', 'arc', 'ra', 'c', 'abc', 'do', 'aa', 'rr'];
// 构建可用字母频次映射:['a' => 1, 'c' => 1, 'r' => 2]
$letterCounts = array_count_values($letters);
$filtered = array_filter($words, function($word) use ($letterCounts) {
// 安全分割单词为字符(支持 UTF-8)
$chars = mb_str_split($word);
$wordLetterCounts = array_count_values($chars);
// 校验每个字符及其频次
foreach ($wordLetterCounts as $char => $count) {
if (!isset($letterCounts[$char]) || $letterCounts[$char] < $count) {
return false; // 违反约束:字符非法 或 频次超限
}
}
return true; // 全部通过校验
});
// 注意:array_filter 保留原键名,如需重置索引可加 array_values()
$result = array_values($filtered);
print_r($result);
// 输出:Array ( [0] => carr [1] => car [2] => arc [3] => ra [4] => c [5] => rr )⚠️ 注意事项:
- 必须使用
mb_str_split()(而非str_split())以正确处理 UTF-8 字符串,避免多字节字符被错误截断; -
array_filter()默认保留原始数组键名,若需连续数字索引,请包裹array_values(); - 该逻辑区分大小写(如
'A'与'a'视为不同字符),如需忽略大小写,可在统计前统一转换为小写(mb_strtolower($word)); - 时间复杂度为 O(N × M),其中 N 是单词数,M 是平均单词长度,适用于中等规模数据;超大规模场景建议预编译频次检查逻辑或改用生成器优化内存。
此方法逻辑清晰、可读性强,是解决“有限字母资源下的单词匹配”问题的标准实践方案。

















