
本文介绍两种优化 php 数组按键前缀分组的方法:一种是简洁清晰的嵌套 foreach + strpos 匹配,另一种是基于正则提取前缀的一次遍历法,显著提升可读性与性能。
本文介绍两种优化 php 数组按键前缀分组的方法:一种是简洁清晰的嵌套 foreach + strpos 匹配,另一种是基于正则提取前缀的一次遍历法,显著提升可读性与性能。
在处理表单提交、批量导入或结构化键名数据时,常需将形如 input_tickettype1_storeno_00、input_tickettype1_deliverydate_01 的键按公共前缀(如 input_tickettype1_storeno)归类,并将对应值按序组织为索引数组。原始代码使用三层嵌套循环加 str_contains() 判断,逻辑冗余、时间复杂度高(O(n×m×k)),且初始化方式不够直观。
以下提供两种更优解法,兼顾可读性、性能与健壮性:
✅ 方法一:双层 foreach + 前缀精确匹配(推荐入门 & 中小数据量)
利用 strpos($key, $prefix) === 0 替代模糊包含判断,确保仅匹配开头完全一致的键(避免 storeno_01 被误匹配到 storeno_011 或 bestoreno_01)。同时省去冗余初始化步骤,直接构建关联结构:
$f = [];
foreach ($h as $prefix) {
$f[$prefix] = []; // 初始化空数组
foreach ($i as $key => $val) {
if (strpos($key, $prefix) === 0) {
$f[$prefix][] = $val;
}
}
}
// 输出结构:['input_tickettype1_storeno' => ['', '9874', '8547', '9214'], ...]⚠️ 注意:此方法仍为 O(n×m) 时间复杂度,当 $h(前缀列表)和 $i(源数据)规模均较大时(如 >1000 项),性能会明显下降。
✅ 方法二:单次遍历 + 正则提取前缀(推荐大数据量 & 结构固定场景)
若键名格式严格遵循 prefix_suffix 模式(如 xxx_yyy_zzz_NN,其中末尾为下划线+数字),可仅遍历源数组一次,用正则提取公共前缀,动态构建分组:
$f = [];
foreach ($i as $key => $value) {
if (preg_match('/^(.+)_[0-9]+$/u', $key, $matches)) {
$prefix = $matches[1];
if (!isset($f[$prefix])) {
$f[$prefix] = [];
}
$f[$prefix][] = $value;
}
}
// 自动支持任意前缀,无需预定义 $h 数组✅ 优势:时间复杂度降至 O(n),且不依赖 $h 预定义,天然支持动态新增字段类型。
⚠️ 注意:需确保键名末尾数字格式统一;若存在无数字后缀的键(如 input_tickettype1_storeno),建议增强正则为 /^(.+?)(?:_[0-9]+)?$/ 并做空值容错。
? 最终建议与总结
- 优先选用方法一:代码意图明确、调试友好、兼容性强,适合绝大多数业务场景;
- 方法二适用于高频调用或超大数组(如万级键值),但需严格约束输入格式;
- 两种方案均避免了原始代码中 array_push($f[$x], $iv) 的非关联索引写法,输出结构更符合 PHP 关联数组语义;
- 如需保持 $h 中前缀的顺序(如保证 storeno 在 deliverydate 前),方法一可直接保留 $h 遍历顺序;方法二若需排序,可在最后执行 uksort($f, fn($a, $b) => array_search($a, $h) <=> array_search($b, $h));。
通过合理选择分组策略,既能精简代码至 5 行以内,又能提升可维护性与运行效率——让数据结构真正服务于业务逻辑,而非成为负担。

















