
在处理来自某些系统(如 virsh domstats 命令输出)的数据时,我们常会遇到一种扁平化的数组结构。这种数组中的每个元素通常包含一个 name 字段和一个 value 字段,其中 name 字段采用点分隔的字符串形式来表示数据的层次结构。
原始数据示例:
$inputArray = [
[ 'name' => 'block.0.name', 'value' => 'vda' ],
[ 'name' => 'block.0.backingIndex', 'value' => 2 ],
[ 'name' => 'block.0.rd.reqs', 'value' => 248907 ],
// ... 更多 block.0 的数据
[ 'name' => 'block.1.name', 'value' => 'hda' ],
[ 'name' => 'block.1.backingIndex', 'value' => 30 ],
// ... 更多 block.1 的数据
[ 'name' => 'vcpu.0.state', 'value' => 1 ],
[ 'name' => 'vcpu.1.time', 'value' => 936409070000000 ],
// ... 更多 vcpu 的数据
[ 'name' => 'balloon.current', 'value' => 16777216 ],
[ 'name' => 'balloon.maximum', 'value' => 16777216 ],
// ... 更多 balloon 的数据
];我们希望将这种扁平的结构转换为一个更具可读性和逻辑性的多维数组,其结构能够反映 name 字段中隐含的层次关系。
期望输出结构示例:
$outputArray = [
'blocks' => [
'block0' => [
'backingIndex' => 2,
'rd.reqs' => 248907,
// ...
],
'block1' => [
'backingIndex' => 30,
'rd.reqs' => 2871,
// ...
],
],
'vcpus' => [
'vcpu0' => [
'state' => 1,
'time' => 963654400000000,
// ...
],
// ...
],
'balloons' => [
'balloon' => [ // 注意这里没有数字索引
'current' => 16777216,
'maximum' => 16777216,
// ...
],
],
];可以看到,转换的关键在于:
立即学习“PHP免费学习笔记(深入)”;
解决此问题的核心思想是遍历原始数组,对每个元素的 name 字符串进行解析,并根据解析结果动态地构建目标多维数组的层次结构。我们将使用 PHP 的字符串和数组处理函数来实现这一目标。
<?php
$inputArray = [
[ 'name' => 'block.0.name', 'value' => 'vda' ],
[ 'name' => 'block.0.backingIndex', 'value' => 2 ],
[ 'name' => 'block.0.rd.reqs', 'value' => 248907 ],
[ 'name' => 'block.0.rd.bytes', 'value' => 9842014208 ],
[ 'name' => 'block.0.rd.times', 'value' => 372870570891 ],
[ 'name' => 'block.0.wr.reqs', 'value' => 6869976 ],
[ 'name' => 'block.0.wr.bytes', 'value' => 50781960192 ],
[ 'name' => 'block.0.wr.times', 'value' => 32361608225142 ],
[ 'name' => 'block.0.fl.reqs', 'value' => 2471825 ],
[ 'name' => 'block.0.fl.times', 'value' => 936802992509 ],
[ 'name' => 'block.0.allocation', 'value' => 21107503104 ],
[ 'name' => 'block.0.capacity', 'value' => 21474836480 ],
[ 'name' => 'block.0.physical', 'value' => 21474836480 ],
[ 'name' => 'block.1.name', 'value' => 'hda' ],
[ 'name' => 'block.1.path', 'value' => '/var/datastores/disk.1' ],
[ 'name' => 'block.1.backingIndex', 'value' => 30 ],
[ 'name' => 'block.1.rd.reqs', 'value' => 2871 ],
[ 'name' => 'block.1.rd.bytes', 'value' => 9677156 ],
[ 'name' => 'block.1.rd.times', 'value' => 620637479 ],
[ 'name' => 'block.1.capacity', 'value' => 374784 ],
[ 'name' => 'block.1.physical', 'value' => 376832 ],
// 假设还有 block.2 的数据,为了演示输出
[ 'name' => 'block.2.backingIndex', 'value' => 30 ],
[ 'name' => 'block.2.rd.reqs', 'value' => 2871 ],
[ 'name' => 'block.2.rd.bytes', 'value' => 9677156 ],
[ 'name' => 'block.2.rd.times', 'value' => 620637479 ],
[ 'name' => 'vcpu.0.state', 'value' => 1 ],
[ 'name' => 'vcpu.0.time', 'value' => 963654400000000 ],
[ 'name' => 'vcpu.0.wait', 'value' => 0 ],
[ 'name' => 'vcpu.1.state', 'value' => 1 ],
[ 'name' => 'vcpu.1.time', 'value' => 936409070000000 ],
[ 'name' => 'vcpu.1.wait', 'value' => 0 ],
[ 'name' => 'vcpu.2.state', 'value' => 1 ],
[ 'name' => 'vcpu.2.time', 'value' => 943396180000000 ],
[ 'name' => 'vcpu.2.wait', 'value' => 0 ],
[ 'name' => 'vcpu.3.state', 'value' => 1 ],
[ 'name' => 'vcpu.3.time', 'value' => 959496330000000 ],
[ 'name' => 'vcpu.3.wait', 'value' => 0 ],
[ 'name' => 'balloon.current', 'value' => 16777216 ],
[ 'name' => 'balloon.maximum', 'value' => 34534530 ], // 示例值修改
[ 'name' => 'balloon.swap_in', 'value' => 0 ],
[ 'name' => 'balloon.swap_out', 'value' => 0 ],
[ 'name' => 'balloon.major_fault', 'value' => 262 ],
[ 'name' => 'balloon.minor_fault', 'value' => 132293 ],
[ 'name' => 'balloon.unused', 'value' => 16153712 ],
[ 'name' => 'balloon.available', 'value' => 16396312 ],
];
$result = [];
foreach ($inputArray as ['name' => $name, 'value' => $value]) {
// 1. 将点分隔的字符串拆分成数组
$parts = explode('.', $name);
// 2. 确定顶层键 (e.g., 'block' -> 'blocks')
$parentKey = $parts[0] . 's';
// 3. 确定子层键 (e.g., 'block.0' -> 'block0', 'balloon' -> 'balloon')
// ctype_digit($parts[1]) 检查第二个部分是否为数字
// 如果是数字,则从 $parts 中移除前两个元素并拼接成 childKey
// 如果不是数字,则只从 $parts 中移除第一个元素并作为 childKey
$childKeySegments = array_splice($parts, 0, ctype_digit($parts[1]) ? 2 : 1);
$childKey = implode('', $childKeySegments); // 例如 block0, vcpu0, balloon
// 4. 确定孙子层键 (剩余的部分用点连接)
// $parts 数组已经被 array_splice() 修改,只剩下孙子层键的组成部分
$grandchildKey = implode('.', $parts);
// 5. 排除不需要的键(如原始的 'name' 字段)
// 如果 grandchildKey 为空,说明原始 name 只有两部分且第二部分是数字,
// 或者原始 name 只有一部分,这两种情况都意味着没有更深层次的键。
// 在本例中,原始的 'block.0.name' 的 'name' 部分应该被排除,
// 因为 'block0' 已经代表了名称。
if ($grandchildKey !== 'name') {
$result[$parentKey][$childKey][$grandchildKey] = $value;
}
}
// 输出结果
echo '<pre>';
var_export($result);
echo '</pre>';
?>通过上述方法,我们可以将扁平化的、使用点分隔键名的数据集,高效且优雅地转换为易于理解和操作的多维数组结构,极大地提升了数据的可用性和代码的可维护性。
以上就是将点分隔字符串转换为多维数组的PHP教程的详细内容,更多请关注php中文网其它相关文章!
PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号