解析以点分隔的字符串并制作多维数组
Parse dot-delimited strings and make a multidimensional array
我有一个看起来像这样的数组
[1] => Array
(
[name] => block.0.name
[value] => vda
)
[2] => Array
(
[name] => block.0.backingIndex
[value] => 2
)
[3] => Array
(
[name] => block.0.rd.reqs
[value] => 248907
)
[4] => Array
(
[name] => block.0.rd.bytes
[value] => 9842014208
)
[5] => Array
(
[name] => block.0.rd.times
[value] => 372870570891
)
[6] => Array
(
[name] => block.0.wr.reqs
[value] => 6869976
)
[7] => Array
(
[name] => block.0.wr.bytes
[value] => 50781960192
)
[8] => Array
(
[name] => block.0.wr.times
[value] => 32361608225142
)
[9] => Array
(
[name] => block.0.fl.reqs
[value] => 2471825
)
[10] => Array
(
[name] => block.0.fl.times
[value] => 936802992509
)
[11] => Array
(
[name] => block.0.allocation
[value] => 21107503104
)
[12] => Array
(
[name] => block.0.capacity
[value] => 21474836480
)
[13] => Array
(
[name] => block.0.physical
[value] => 21474836480
)
[14] => Array
(
[name] => block.1.name
[value] => hda
)
[15] => Array
(
[name] => block.1.path
[value] => /var/datastores/disk.1
)
[16] => Array
(
[name] => block.1.backingIndex
[value] => 30
)
[17] => Array
(
[name] => block.1.rd.reqs
[value] => 2871
)
[18] => Array
(
[name] => block.1.rd.bytes
[value] => 9677156
)
[19] => Array
(
[name] => block.1.rd.times
[value] => 620637479
)
[20] => Array
(
[name] => block.1.capacity
[value] => 374784
)
[21] => Array
(
[name] => block.1.physical
[value] => 376832
)
我需要让数组看起来像下面这样
[blocks] => Array
(
[block0] => Array
(
[backingIndex] => 2
[rd.reqs] => 2480907
[rd.bytes] => 9842014208
[rd.times] = > 372870570891
............
)
[block1] => Array
(
[backingIndex] => 30
[rd.reqs] => 2871
[rd.bytes] => 9677156
[rd.times] = > 620637479
............
)
)
值得注意的是,该数组包含更多项目,并且将包含
vcpu.0.state=1
vcpu.0.time=963654400000000
vcpu.0.wait=0
vcpu.1.state=1
vcpu.1.time=936409070000000
vcpu.1.wait=0
vcpu.2.state=1
vcpu.2.time=943396180000000
vcpu.2.wait=0
vcpu.3.state=1
vcpu.3.time=959496330000000
vcpu.3.wait=0
应该创建一个相似的子集
但有些值没有整数索引,例如
balloon.current=16777216
balloon.maximum=16777216
balloon.swap_in=0
balloon.swap_out=0
balloon.major_fault=262
balloon.minor_fault=132293
balloon.unused=16153712
balloon.available=16396312
我可以通过使用循环和寻找特定的字符串来做到这一点,但时间和开销似乎不值得,我希望能够创建一个基于部分字符串的子数组,如
block.0.rd.reqs
-> arrayName.index.value
如果没有超过 100 行代码和极长的执行时间,我似乎无法让它工作。
此信息来自 运行 Virsh domstats 命令。
修改了我的答案以支持非索引并且不知道什么是关键。
索引部分很简单。
对于无索引我用is_numeric看有没有索引,区别对待创建
我所做的是正确循环并使用一些爆炸...知道这个数组在名称 dot something 中有某种逻辑。
所以我构建了你的数组的一个版本,之后我使用 explode 循环遍历它,根据你的需要剪切块的名称,这样我什至不需要知道我在循环...:)
看看我是如何将键赋予新数组的。
您当然可以根据从爆炸值中获得的名称禁用某些创建。
<?php
$Array[] = ['name' => "block.0.name", 'value' => 'vda'];
$Array[] = ['name' => "block.0.backingIndex", 'value' => '2'];
$Array[] = ['name' => "block.0.rd.reqs", 'value' => '248907'];
$Array[] = ['name' => "block.0.rd.bytes", 'value' => '9842014208'];
$Array[] = ['name' => "block.0.rd.times", 'value' => '372870570891'];
$Array[] = ['name' => "block.1.name", 'value' => 'hda'];
$Array[] = ['name' => "block.1.backingIndex", 'value' => '30'];
$Array[] = ['name' => "block.1.rd.reqs", 'value' => '2871'];
$Array[] = ['name' => "block.1.rd.bytes", 'value' => '9677156'];
$Array[] = ['name' => "block.1.rd.times", 'value' => '620637479'];
$Array[] = ['name' => "block.2.name", 'value' => 'cda'];
$Array[] = ['name' => "block.2.backingIndex", 'value' => '30'];
$Array[] = ['name' => "block.2.rd.reqs", 'value' => '2871'];
$Array[] = ['name' => "block.2.rd.bytes", 'value' => '9677156'];
$Array[] = ['name' => "block.2.rd.times", 'value' => '620637479'];
$Array[] = ['name' => "balloon.current", 'value' => '16777216'];
$Array[] = ['name' => "balloon.maximum", 'value' => '34534530'];
$Array[] = ['name' => "balloon.rd.reqs", 'value' => '45645645'];
$Array[] = ['name' => "balloon.rd.bytes", 'value' => '967435345347156'];
$Array[] = ['name' => "balloon.rd.times", 'value' => '324234'];
/*echo '<pre>';
print_r($Array);*/
foreach($Array as $val){
$sVal = explode(".",$val['name']);
if(is_numeric($sVal[1])){
$Val = str_replace($sVal[0].".".$sVal[1].".","",$val['name']);
$newArray[$sVal[0].'s'][$sVal[0] . $sVal[1]][$Val] = $val['value'];
} else {
$Val = str_replace($sVal[0].".","",$val['name']);
$newArray[$sVal[0].'s'][$sVal[0]][$Val] = $val['value'];
}
}
echo '<pre>';
print_r($newArray);
会 return:
Array
(
[blocks] => Array
(
[block0] => Array
(
[name] => vda
[backingIndex] => 2
[rd.reqs] => 248907
[rd.bytes] => 9842014208
[rd.times] => 372870570891
)
[block1] => Array
(
[name] => hda
[backingIndex] => 30
[rd.reqs] => 2871
[rd.bytes] => 9677156
[rd.times] => 620637479
)
[block2] => Array
(
[name] => cda
[backingIndex] => 30
[rd.reqs] => 2871
[rd.bytes] => 9677156
[rd.times] => 620637479
)
)
[balloons] => Array
(
[balloon] => Array
(
[current] => 16777216
[maximum] => 34534530
[rd.reqs] => 45645645
[rd.bytes] => 967435345347156
[rd.times] => 324234
)
)
)
除了遍历数组和解析字符串之外没有其他解决方案。我 猜测 输入和输出之间的映射 - 从你的例子和你的叙述中都不清楚。它当然不需要100+行代码!
<?php
$base_pattern="/^(block)\.(\d+)\.(.*)$/";
$alt_pattern="/^(balloon)\.(.*)$/";
$out=array();
foreach($input_array[1] as $a) {
if (preg_match($base_pattern, $a['name'], $match)) {
// split base.123.something into 'base.', '123', 'something'
// you could also use explode
$key=$match[1] . $match[2];
} else if (preg_match($alt_pattern, $a['name'], $match)) {
$key=$match[1];
} else {
continue; // for entries which don't follow the pattern
}
if (!isset($out[$key])) { $out[$key] = array(); }
$attribute=array_pop($match);
$out[$key][$attribute]=$a['value'];
}
通常,我会向您指出 Convert dot syntax like "this.that.other" to multi-dimensional array in PHP 并将这个问题作为一个研究不足的重复问题进行锤击,但您似乎在期望的输出中有足够的偏差。
你的示例输入和期望的输出在你的问题中没有很好地表达,但如果我正确地逆向工程你的要求,你只需要分解名称值,做一些条件准备,然后将值推入 3 -级输出数组。
代码:(Demo)
$result = [];
foreach ($array as ['name' => $name, 'value' => $value]) {
$parts = explode('.', $name);
$parentKey = $parts[0] . 's';
$childKey = implode(array_splice($parts, 0, ctype_digit($parts[1]) ? 2 : 1));
$grandchildKey = implode('.', $parts); // $parts was reduced by array_splice()
if ($grandchildKey !== 'name') {
$result[$parentKey][$childKey][$grandchildKey] = $value;
}
}
var_export($result);
输出:
array (
'blocks' =>
array (
'block0' =>
array (
'backingIndex' => 2,
'rd.reqs' => 248907,
'rd.bytes' => 9842014208,
'rd.times' => 372870570891,
),
'block1' =>
array (
'backingIndex' => 30,
'rd.reqs' => 2871,
'rd.bytes' => 9677156,
'rd.times' => 620637479,
),
'block2' =>
array (
'backingIndex' => 30,
'rd.reqs' => 2871,
'rd.bytes' => 9677156,
'rd.times' => 620637479,
),
),
'vcpus' =>
array (
'vcpu0' =>
array (
'state' => 1,
'time' => 963654400000000,
'wait' => 0,
),
'vcpu1' =>
array (
'state' => 1,
'time' => 936409070000000,
'wait' => 0,
),
'vcpu2' =>
array (
'state' => 1,
'time' => 943396180000000,
'wait' => 0,
),
'vcpu3' =>
array (
'state' => 1,
'time' => 959496330000000,
'wait' => 0,
),
),
'balloons' =>
array (
'balloon' =>
array (
'current' => 16777216,
'maximum' => 34534530,
'swap_in' => 0,
'swap_out' => 0,
'major_fault' => 262,
'minor_fault' => 132293,
'unused' => 16153712,
'available' => 16396312,
),
),
)
这是我必须为@mickmackusa 的回答做的事情
function test($array){
$compiled = [];
foreach($array as $item)
{
$result = [];
foreach ($item as ['name' => $name, 'value' => $value]) {
$parts = explode('.', $name);
$parentKey = $parts[0] . 's';
$childKey = implode(array_splice($parts, 0, ctype_digit($parts[1]) ? 2 : 1));
$grandchildKey = implode('.', $parts);
if ($grandchildKey !== 'name') {
$result[$parentKey][$childKey][$grandchildKey] = $value;
}
}
array_push($compiled, $result);
}
return $compiled;
}
除了添加额外的 foreach 循环外,它完美地工作并且将我的代码行减少了 77 行
我有一个看起来像这样的数组
[1] => Array
(
[name] => block.0.name
[value] => vda
)
[2] => Array
(
[name] => block.0.backingIndex
[value] => 2
)
[3] => Array
(
[name] => block.0.rd.reqs
[value] => 248907
)
[4] => Array
(
[name] => block.0.rd.bytes
[value] => 9842014208
)
[5] => Array
(
[name] => block.0.rd.times
[value] => 372870570891
)
[6] => Array
(
[name] => block.0.wr.reqs
[value] => 6869976
)
[7] => Array
(
[name] => block.0.wr.bytes
[value] => 50781960192
)
[8] => Array
(
[name] => block.0.wr.times
[value] => 32361608225142
)
[9] => Array
(
[name] => block.0.fl.reqs
[value] => 2471825
)
[10] => Array
(
[name] => block.0.fl.times
[value] => 936802992509
)
[11] => Array
(
[name] => block.0.allocation
[value] => 21107503104
)
[12] => Array
(
[name] => block.0.capacity
[value] => 21474836480
)
[13] => Array
(
[name] => block.0.physical
[value] => 21474836480
)
[14] => Array
(
[name] => block.1.name
[value] => hda
)
[15] => Array
(
[name] => block.1.path
[value] => /var/datastores/disk.1
)
[16] => Array
(
[name] => block.1.backingIndex
[value] => 30
)
[17] => Array
(
[name] => block.1.rd.reqs
[value] => 2871
)
[18] => Array
(
[name] => block.1.rd.bytes
[value] => 9677156
)
[19] => Array
(
[name] => block.1.rd.times
[value] => 620637479
)
[20] => Array
(
[name] => block.1.capacity
[value] => 374784
)
[21] => Array
(
[name] => block.1.physical
[value] => 376832
)
我需要让数组看起来像下面这样
[blocks] => Array
(
[block0] => Array
(
[backingIndex] => 2
[rd.reqs] => 2480907
[rd.bytes] => 9842014208
[rd.times] = > 372870570891
............
)
[block1] => Array
(
[backingIndex] => 30
[rd.reqs] => 2871
[rd.bytes] => 9677156
[rd.times] = > 620637479
............
)
)
值得注意的是,该数组包含更多项目,并且将包含
vcpu.0.state=1
vcpu.0.time=963654400000000
vcpu.0.wait=0
vcpu.1.state=1
vcpu.1.time=936409070000000
vcpu.1.wait=0
vcpu.2.state=1
vcpu.2.time=943396180000000
vcpu.2.wait=0
vcpu.3.state=1
vcpu.3.time=959496330000000
vcpu.3.wait=0
应该创建一个相似的子集
但有些值没有整数索引,例如
balloon.current=16777216
balloon.maximum=16777216
balloon.swap_in=0
balloon.swap_out=0
balloon.major_fault=262
balloon.minor_fault=132293
balloon.unused=16153712
balloon.available=16396312
我可以通过使用循环和寻找特定的字符串来做到这一点,但时间和开销似乎不值得,我希望能够创建一个基于部分字符串的子数组,如
block.0.rd.reqs
-> arrayName.index.value
如果没有超过 100 行代码和极长的执行时间,我似乎无法让它工作。
此信息来自 运行 Virsh domstats 命令。
修改了我的答案以支持非索引并且不知道什么是关键。
索引部分很简单。 对于无索引我用is_numeric看有没有索引,区别对待创建
我所做的是正确循环并使用一些爆炸...知道这个数组在名称 dot something 中有某种逻辑。
所以我构建了你的数组的一个版本,之后我使用 explode 循环遍历它,根据你的需要剪切块的名称,这样我什至不需要知道我在循环...:)
看看我是如何将键赋予新数组的。
您当然可以根据从爆炸值中获得的名称禁用某些创建。
<?php
$Array[] = ['name' => "block.0.name", 'value' => 'vda'];
$Array[] = ['name' => "block.0.backingIndex", 'value' => '2'];
$Array[] = ['name' => "block.0.rd.reqs", 'value' => '248907'];
$Array[] = ['name' => "block.0.rd.bytes", 'value' => '9842014208'];
$Array[] = ['name' => "block.0.rd.times", 'value' => '372870570891'];
$Array[] = ['name' => "block.1.name", 'value' => 'hda'];
$Array[] = ['name' => "block.1.backingIndex", 'value' => '30'];
$Array[] = ['name' => "block.1.rd.reqs", 'value' => '2871'];
$Array[] = ['name' => "block.1.rd.bytes", 'value' => '9677156'];
$Array[] = ['name' => "block.1.rd.times", 'value' => '620637479'];
$Array[] = ['name' => "block.2.name", 'value' => 'cda'];
$Array[] = ['name' => "block.2.backingIndex", 'value' => '30'];
$Array[] = ['name' => "block.2.rd.reqs", 'value' => '2871'];
$Array[] = ['name' => "block.2.rd.bytes", 'value' => '9677156'];
$Array[] = ['name' => "block.2.rd.times", 'value' => '620637479'];
$Array[] = ['name' => "balloon.current", 'value' => '16777216'];
$Array[] = ['name' => "balloon.maximum", 'value' => '34534530'];
$Array[] = ['name' => "balloon.rd.reqs", 'value' => '45645645'];
$Array[] = ['name' => "balloon.rd.bytes", 'value' => '967435345347156'];
$Array[] = ['name' => "balloon.rd.times", 'value' => '324234'];
/*echo '<pre>';
print_r($Array);*/
foreach($Array as $val){
$sVal = explode(".",$val['name']);
if(is_numeric($sVal[1])){
$Val = str_replace($sVal[0].".".$sVal[1].".","",$val['name']);
$newArray[$sVal[0].'s'][$sVal[0] . $sVal[1]][$Val] = $val['value'];
} else {
$Val = str_replace($sVal[0].".","",$val['name']);
$newArray[$sVal[0].'s'][$sVal[0]][$Val] = $val['value'];
}
}
echo '<pre>';
print_r($newArray);
会 return:
Array
(
[blocks] => Array
(
[block0] => Array
(
[name] => vda
[backingIndex] => 2
[rd.reqs] => 248907
[rd.bytes] => 9842014208
[rd.times] => 372870570891
)
[block1] => Array
(
[name] => hda
[backingIndex] => 30
[rd.reqs] => 2871
[rd.bytes] => 9677156
[rd.times] => 620637479
)
[block2] => Array
(
[name] => cda
[backingIndex] => 30
[rd.reqs] => 2871
[rd.bytes] => 9677156
[rd.times] => 620637479
)
)
[balloons] => Array
(
[balloon] => Array
(
[current] => 16777216
[maximum] => 34534530
[rd.reqs] => 45645645
[rd.bytes] => 967435345347156
[rd.times] => 324234
)
)
)
除了遍历数组和解析字符串之外没有其他解决方案。我 猜测 输入和输出之间的映射 - 从你的例子和你的叙述中都不清楚。它当然不需要100+行代码!
<?php
$base_pattern="/^(block)\.(\d+)\.(.*)$/";
$alt_pattern="/^(balloon)\.(.*)$/";
$out=array();
foreach($input_array[1] as $a) {
if (preg_match($base_pattern, $a['name'], $match)) {
// split base.123.something into 'base.', '123', 'something'
// you could also use explode
$key=$match[1] . $match[2];
} else if (preg_match($alt_pattern, $a['name'], $match)) {
$key=$match[1];
} else {
continue; // for entries which don't follow the pattern
}
if (!isset($out[$key])) { $out[$key] = array(); }
$attribute=array_pop($match);
$out[$key][$attribute]=$a['value'];
}
通常,我会向您指出 Convert dot syntax like "this.that.other" to multi-dimensional array in PHP 并将这个问题作为一个研究不足的重复问题进行锤击,但您似乎在期望的输出中有足够的偏差。
你的示例输入和期望的输出在你的问题中没有很好地表达,但如果我正确地逆向工程你的要求,你只需要分解名称值,做一些条件准备,然后将值推入 3 -级输出数组。
代码:(Demo)
$result = [];
foreach ($array as ['name' => $name, 'value' => $value]) {
$parts = explode('.', $name);
$parentKey = $parts[0] . 's';
$childKey = implode(array_splice($parts, 0, ctype_digit($parts[1]) ? 2 : 1));
$grandchildKey = implode('.', $parts); // $parts was reduced by array_splice()
if ($grandchildKey !== 'name') {
$result[$parentKey][$childKey][$grandchildKey] = $value;
}
}
var_export($result);
输出:
array (
'blocks' =>
array (
'block0' =>
array (
'backingIndex' => 2,
'rd.reqs' => 248907,
'rd.bytes' => 9842014208,
'rd.times' => 372870570891,
),
'block1' =>
array (
'backingIndex' => 30,
'rd.reqs' => 2871,
'rd.bytes' => 9677156,
'rd.times' => 620637479,
),
'block2' =>
array (
'backingIndex' => 30,
'rd.reqs' => 2871,
'rd.bytes' => 9677156,
'rd.times' => 620637479,
),
),
'vcpus' =>
array (
'vcpu0' =>
array (
'state' => 1,
'time' => 963654400000000,
'wait' => 0,
),
'vcpu1' =>
array (
'state' => 1,
'time' => 936409070000000,
'wait' => 0,
),
'vcpu2' =>
array (
'state' => 1,
'time' => 943396180000000,
'wait' => 0,
),
'vcpu3' =>
array (
'state' => 1,
'time' => 959496330000000,
'wait' => 0,
),
),
'balloons' =>
array (
'balloon' =>
array (
'current' => 16777216,
'maximum' => 34534530,
'swap_in' => 0,
'swap_out' => 0,
'major_fault' => 262,
'minor_fault' => 132293,
'unused' => 16153712,
'available' => 16396312,
),
),
)
这是我必须为@mickmackusa 的回答做的事情
function test($array){
$compiled = [];
foreach($array as $item)
{
$result = [];
foreach ($item as ['name' => $name, 'value' => $value]) {
$parts = explode('.', $name);
$parentKey = $parts[0] . 's';
$childKey = implode(array_splice($parts, 0, ctype_digit($parts[1]) ? 2 : 1));
$grandchildKey = implode('.', $parts);
if ($grandchildKey !== 'name') {
$result[$parentKey][$childKey][$grandchildKey] = $value;
}
}
array_push($compiled, $result);
}
return $compiled;
}
除了添加额外的 foreach 循环外,它完美地工作并且将我的代码行减少了 77 行