PHP:字符串包含指定子串且排除其他子串的编码分配优化实现咨询
你的问题我太懂了——手动写一堆if-else处理多颜色组合不仅容易出错,扩展性还极差,尤其是要支持6种颜色、10个对象的场景,简直是维护噩梦。先帮你拆解下原来代码的问题,再给你一个简洁可复用的方案:
先说说你原来代码的问题
你的else if顺序是先判断单个颜色(比如red),再判断组合(red+blue)。当字符串同时包含red和blue时,第一个判断strpos($mystring, 'red')就会命中,直接把code设为2,根本轮不到后面的组合判断。这是逻辑顺序的硬伤,而且就算调整顺序,手动写所有组合也会让代码量爆炸。
简洁可复用的解决方案
核心思路是把匹配规则和业务逻辑分离:用配置数组定义所有规则(从优先级高的组合到低优先级的单个),然后封装成通用函数来处理匹配。这样不管是新增颜色、组合,还是切换到其他对象,只需要修改配置数组就行,完全不用碰核心逻辑。
代码示例
/** * 根据字符串包含的子串组合返回对应编码 * @param string $string 待匹配的字符串 * @param array $rules 匹配规则数组,每个元素包含['substrings' => [...], 'code' => 数字] * @param string $baseSubstr 基础对象(比如balloon) * @param int $baseCode 仅包含基础对象时的编码 * @return int|null 匹配到的编码,无匹配或无基础对象时返回null */ function getTargetCode($string, $rules, $baseSubstr, $baseCode) { // 先检查基础对象是否存在,不存在直接返回 if (strpos($string, $baseSubstr) === false) { return null; } // 按优先级遍历规则,找到第一个匹配的就返回编码 foreach ($rules as $rule) { // 用正向预查正则确保所有子串都存在(比多次strpos更简洁) $pattern = '/'; foreach ($rule['substrings'] as $substr) { // 转义特殊字符,避免正则报错 $pattern .= '(?=.*' . preg_quote($substr, '/') . ')'; } $pattern .= '/i'; // 可选:i表示不区分大小写,根据需求调整 if (preg_match($pattern, $string)) { return $rule['code']; } } // 检查是否仅包含基础对象(不包含任何规则里的子串) $allSubstrings = []; foreach ($rules as $rule) { $allSubstrings = array_merge($allSubstrings, $rule['substrings']); } $allSubstrings = array_unique($allSubstrings); $hasAnySubstr = false; foreach ($allSubstrings as $substr) { if (strpos($string, $substr) !== false) { $hasAnySubstr = true; break; } } if (!$hasAnySubstr) { return $baseCode; } // 如果有未匹配到规则的子串,这里可以自定义返回值(比如错误码) return null; } // ------------------------------ // 针对balloon场景的规则配置 // ------------------------------ $balloonColorRules = [ ['substrings' => ['red', 'blue', 'green'], 'code' => 11], ['substrings' => ['red', 'blue'], 'code' => 5], ['substrings' => ['red', 'green'], 'code' => 6], ['substrings' => ['blue', 'green'], 'code' => 7], ['substrings' => ['red'], 'code' => 2], ['substrings' => ['blue'], 'code' => 3], ['substrings' => ['green'], 'code' => 4], ]; // 使用示例 $testString1 = "red blue balloon"; echo getTargetCode($testString1, $balloonColorRules, 'balloon', 1); // 输出5 $testString2 = "balloon"; echo getTargetCode($testString2, $balloonColorRules, 'balloon', 1); // 输出1 $testString3 = "red green balloon"; echo getTargetCode($testString3, $balloonColorRules, 'balloon', 1); // 输出6
方案优势
- 完全可复用:比如你要处理另一个对象(比如car),只需要定义新的规则数组,调用同一个函数就行:
$carColorRules = [ ['substrings' => ['black', 'white'], 'code' => 99], ['substrings' => ['black'], 'code' => 88], // ...其他规则 ]; getTargetCode("black car", $carColorRules, 'car', 100);
- 扩展性极强:新增颜色或者组合时,只需要在规则数组里加一行,比如要加yellow,编码8,同时red+yellow编码12,直接加:
$balloonColorRules = [ ['substrings' => ['red', 'blue', 'green'], 'code' => 11], ['substrings' => ['red', 'yellow'], 'code' => 12], // 新增组合规则 // ...原有规则 ['substrings' => ['yellow'], 'code' => 8], // 新增单个规则 ];
- 逻辑清晰:规则按优先级从高到低排列,复杂组合先匹配,避免了嵌套if-else的混乱。
内容的提问来源于stack exchange,提问作者user3313268
相关产品推荐
相关产品推荐

