
本文介绍如何将包含2200个TLD的扁平数组,按主顶级域(如 .aero)与其下属通用顶级域(如 .airport.aero)的关系,重构为嵌套结构数组,确保逻辑准确、性能高效且代码简洁可维护。
本文介绍如何将包含2200个tld的扁平数组,按主顶级域(如 `.aero`)与其下属通用顶级域(如 `.airport.aero`)的关系,重构为嵌套结构数组,确保逻辑准确、性能高效且代码简洁可维护。
在实际域名管理或DNS校验场景中,常需区分基础TLD(如 .aero、.aetna)与其派生的二级gTLD(如 .airport.aero)。原始数组是无序扁平结构,而目标结构要求:每个主TLD作为独立条目,其 gTLD 字段为对应子域名组成的数组(若无则为空数组),且最终输出为索引数字键的有序列表。
以下为推荐实现方案(基于 array_reduce + array_values 的函数式写法):
$TestArray = ['.aero', '.airport.aero', '.cargo.aero', '.charter.aero', '.aetna'];
$result = array_values(
array_reduce(
$TestArray,
function ($carry, $item) {
// 主TLD:仅含1个点(如 .aero)
if (substr_count($item, '.') === 1) {
$carry[$item] = ['tld' => $item, 'gTLD' => []];
}
// 子gTLD:含2个及以上点(如 .airport.aero → 归属 .aero)
else {
// 提取最右侧主TLD部分(即最后一个点之后的完整后缀)
$parts = explode('.', ltrim($item, '.'));
$baseTld = '.' . end($parts); // 如 'airport.aero' → '.aero'
// 确保主TLD已存在(避免未定义索引)
if (!isset($carry[$baseTld])) {
$carry[$baseTld] = ['tld' => $baseTld, 'gTLD' => []];
}
$carry[$baseTld]['gTLD'][] = $item;
}
return $carry;
},
[]
)
);
print_r($result);输出结果:
Array
(
[0] => Array
(
[tld] => .aero
[gTLD] => Array
(
[0] => .airport.aero
[1] => .cargo.aero
[2] => .charter.aero
)
)
[1] => Array
(
[tld] => .aetna
[gTLD] => Array
(
)
)
)✅ 关键优势说明:
- 健壮性:使用 explode() + end() 安全提取主TLD后缀,避免正则误匹配;显式检查 $carry[$baseTld] 是否存在,防止PHP警告。
- 顺序无关:不依赖TLD在原数组中的位置(原答案中“gTLD必须出现在主TLD之后”是脆弱假设,本方案已解除该限制)。
- 性能友好:单次遍历 O(n),无需嵌套循环,处理2200项时效率远高于原始双重 foreach(O(n²))。
- 语义清晰:array_reduce 表达“累积归类”的意图,array_values() 确保输出为连续数字索引数组,符合预期结构。
⚠️ 注意事项:
- 若输入含非法格式(如 ..aero 或无前导点的 aero),建议前置校验:array_filter($TestArray, fn($t) => $t[0] === '.' && substr_count($t, '.') >= 1)。
- 对于超大规模数据(如 >50,000 项),可考虑预构建主TLD哈希表加速查找,但2200项无需过度优化。
- 最终结构中 gTLD 始终为数组类型(空数组而非空字符串),便于后续 foreach 遍历,避免类型判断。
此方案兼顾可读性、鲁棒性与扩展性,可直接集成至域名验证、WHOIS解析或TLD分类系统中。

















