PHP7中基于句子匹配分类数组,返回对应子数组ID的最优方案
高性能PHP7实现:句子与分类关键词匹配方案
针对你这个需求,我整理了一个PHP7下性能拉满的实现方案,全程用原生函数搞定,核心思路是通过预处理构建反向映射表,把每次匹配的时间复杂度降到近乎O(1),完美适配你的场景。
核心实现代码
第一步:预处理分类数组,构建关键词映射表
这一步只需要执行一次(如果你的分类数组不会频繁变动,可以把这个映射表缓存起来,进一步提升性能):
$categories = [ "1" => ["fruit", "salad", "vegetable"], "2" => ["beef", "meat", "sausage"], "3" => ["chocolate", "cake", "bread"] ]; // 构建「小写关键词 -> 分类ID」的反向映射,实现大小写不敏感匹配 $keywordMap = []; foreach ($categories as $id => $keywords) { foreach ($keywords as $keyword) { $keywordMap[strtolower($keyword)] = $id; } }
第二步:编写匹配函数
这个函数负责处理输入句子,快速找到对应的分类ID:
function findMatchingCategoryId(string $sentence, array $keywordMap): ?string { // 把句子转小写,用正则拆分出所有有效单词(自动忽略空格、标点等分隔符) $words = preg_split('/\W+/', strtolower($sentence), -1, PREG_SPLIT_NO_EMPTY); // 遍历每个单词,用isset做O(1)的哈希查找 foreach ($words as $word) { if (isset($keywordMap[$word])) { return $keywordMap[$word]; } } return null; // 没有匹配到任何分类时返回null }
测试用例
// 测试正常大小写的句子 $sentence1 = "I love big sausage"; echo findMatchingCategoryId($sentence1, $keywordMap); // 输出:2 // 测试带大写后缀的句子 $sentence2 = "I love big sausageS"; echo findMatchingCategoryId($sentence2, $keywordMap); // 输出:2
性能为什么最优?
- 预处理复用:反向映射表只需要构建一次,后续每次匹配都是基于哈希表的O(1)查找,比每次遍历所有分类关键词的O(m*n)效率高太多(m是分类数,n是关键词数)。
- 原生函数加持:
strtolower、preg_split、isset都是PHP7底层优化过的原生函数,性能比手动实现的逻辑快很多。 - 鲁棒性强:
preg_split能处理各种分隔符(比如句子里的感叹号、逗号),不会因为标点导致匹配失败。
额外优化建议
- 如果你的分类数组非常大,可以考虑把
$keywordMap序列化后缓存到文件或者Redis里,避免每次启动都重新构建。 - 如果需要支持部分匹配(比如句子里的
sausages匹配关键词sausage),可以调整匹配逻辑为stripos,但这会牺牲一些性能(变成O(n*k),k是关键词数),如果不是刚需,不建议这么做。 - 可以把这些逻辑封装成一个工具类,让代码更易维护,比如把
$keywordMap作为类的静态属性,只初始化一次。
内容的提问来源于stack exchange,提问作者Coool6
相关产品推荐
相关产品推荐

