
本文介绍一种高效、简洁的方法,将包含 2200 个条目的 TLD 数组(如 .aero 及其子域 .airport.aero)按主 TLD 与对应 gTLD 子域的关系,重组为结构清晰的二维嵌套数组。
本文介绍一种高效、简洁的方法,将包含 2200 个条目的 tld 数组(如 `.aero` 及其子域 `.airport.aero`)按主 tld 与对应 gtld 子域的关系,重组为结构清晰的二维嵌套数组。
在实际域名管理或 DNS 策略处理中,常需区分「基础顶级域(TLD)」(如 .aero、.aetna)与「国际化通用顶级域下的二级标识(gTLD)」(如 .airport.aero)。原始数组是扁平的字符串列表,而目标结构要求:每个主 TLD 作为独立条目,其 gTLD 键下聚合所有以该 TLD 为后缀的子域(即“under gtld”关系)。
以下是一种基于 PHP 的函数式编程方案,使用 array_reduce() 与正则解析,兼顾可读性与性能:
$TestArray = ['.aero', '.airport.aero', '.cargo.aero', '.charter.aero', '.aetna'];
$result = array_values(
array_reduce(
$TestArray,
function ($carry, $item) {
// 主 TLD:仅含一个点(如 ".aero")
if (substr_count($item, '.') === 1) {
$carry[$item] = [
'tld' => $item,
'gTLD' => []
];
}
// gTLD 子域:含两个及以上点(如 ".airport.aero")
else {
// 提取末尾主 TLD(如从 ".airport.aero" 中提取 ".aero")
$matches = [];
if (preg_match('/.[^.]+.[^.]+$/', $item, $matches)) {
$baseTld = $matches[0];
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
(
)
)
)⚠️ 注意事项:
- 本方案假设所有主 TLD 均为单点格式(如 .aero),且 gTLD 子域严格以主 TLD 为后缀(如 .xxx.aero),不支持 .xxx.yyy.aero 这类三级嵌套。
- 正则 /\.[^.]+\.[^.]+$/ 安全匹配末尾两个点分段(如 .airport.aero → .aero),避免误判 .co.uk 等国家代码变体。
- 若输入数据顺序不确定(即 gTLD 出现在主 TLD 之前),代码仍能正确归并——因 array_reduce 动态初始化主 TLD 条目,无需预排序。
- 对于 2200+ 条目规模,该实现时间复杂度为 O(n),远优于原始嵌套循环的 O(n²),推荐用于生产环境。
最终生成的 $result 是标准索引数组,便于后续 foreach 遍历或 JSON 序列化导出,满足策略配置、前端渲染或 API 接口等典型应用场景。

















