将多维数组解析为完全指定的端点
Resolve a multi dimensional array into fully specified endpoints
我需要使用 PHP 将多维数组(任意维度)中的每个端点转换为包含所有后代节点的行。换句话说,我想解析数组中的每个完整分支。我不确定如何更清楚地说明这一点,所以也许最好的方法是举个例子。
如果我从这样的数组开始:
$arr = array(
'A'=>array(
'a'=>array(
'i'=>1,
'j'=>2),
'b'=>3
),
'B'=>array(
'a'=>array(
'm'=>4,
'n'=>5),
'b'=>6
)
);
数组中有 6 个端点,即数字 1 到 6,我想生成 6 行:
- A,a,i,1
- A,a,j,2
- A,b,2
- B,a,m,3
- B,a,n,4
- B,b,2
每行包含到终点的后代的完整路径。由于数组可以有任意维数,这建议使用递归 PHP 函数,我试过:
function array2Rows($arr, $str='', $out='') {
if (is_array($arr)) {
foreach ($arr as $att => $arr1) {
$str .= ((strlen($str)? ',': '')) . $att;
$out = array2Rows($arr1, $str, $out);
}
echo '<hr />';
} else {
$str .= ((strlen($str)? ',': '')) . $arr;
$out .= ((strlen($out)? '<br />': '')) . $str;
}
return $out;
}
函数调用如下:
echo '<p>'.array2Rows($arr, '', '').'</p>';
这个函数的输出是:
- A,a,i,1
- A,a,i,j,2
- A,a,b,3
- A,B,a,m,4
- A,B,a,m,n,5
- A,B,a,b,6
除了第一个值之外,还有一个是不正确的,因为某些节点上的值是重复的。我已经尝试了递归函数的多种变体,这是我能得到的最接近的。
我将欢迎任何有关如何解决此问题的建议,如果问题的陈述不是很清楚,我深表歉意。
您重复倒数第二个值的原因是,在您的循环中,您在 运行 下一个数组的函数之前附加了键。这样的东西会更好:
function array2Rows($arr, &$out=[], $row = []) {
if (is_array($arr)) {
foreach ($arr as $key => $newArray) {
if (is_array($newArray)) {
$row[] = $key; //If the current value is an array, add its key to the current row
array2Rows($newArray, $out, $row); //process the new value
} else { //The current value is not an array
$out[] = implode(',',array_merge($row,[$key,$newArray])); //Add the current key and value to the row and write to the output
}
}
}
return $out;
}
这是轻微优化并利用参考来保存完整输出。我还将其更改为使用和 return 数组而不是字符串。我发现这两项更改都使函数更具可读性。
如果你想return一个格式类似于你函数中的字符串的字符串,请将最后一行替换为
return implode('<br>', $out);
或者,您可以在调用时执行此操作,这就是我所说的此类事情的“最佳实践”;例如
$result = array2Rows($arr);
echo implode('<br>', $result);
请注意,由于这使用了输出参考,因此这也有效:
array2Rows($arr, $result);
echo implode('<br>', $result);
你和你的函数太接近了……我把你的函数拿来稍微修改如下:
function array2Rows($arr, $str='', $csv='') {
$tmp = $str;
if (is_array($arr)) {
foreach ($arr as $att => $arr1) {
$tmp = $str . ((strlen($str)? ', ': '')) . $att;
$csv = array2Rows($arr1, $tmp, $csv);
}
} else {
$tmp .= ((strlen($str)? ', ': '')) . $arr;
$csv .= ((strlen($csv)? '<br />': '')) . $tmp;
}
return $csv;
}
唯一不同的是引入了一个临时变量$tmp,保证每次在递归函数运行之前不改变$str的值。
函数的输出变为:
这个功能不错,我可以想出几个应用程序。
我需要使用 PHP 将多维数组(任意维度)中的每个端点转换为包含所有后代节点的行。换句话说,我想解析数组中的每个完整分支。我不确定如何更清楚地说明这一点,所以也许最好的方法是举个例子。
如果我从这样的数组开始:
$arr = array(
'A'=>array(
'a'=>array(
'i'=>1,
'j'=>2),
'b'=>3
),
'B'=>array(
'a'=>array(
'm'=>4,
'n'=>5),
'b'=>6
)
);
数组中有 6 个端点,即数字 1 到 6,我想生成 6 行:
- A,a,i,1
- A,a,j,2
- A,b,2
- B,a,m,3
- B,a,n,4
- B,b,2
每行包含到终点的后代的完整路径。由于数组可以有任意维数,这建议使用递归 PHP 函数,我试过:
function array2Rows($arr, $str='', $out='') {
if (is_array($arr)) {
foreach ($arr as $att => $arr1) {
$str .= ((strlen($str)? ',': '')) . $att;
$out = array2Rows($arr1, $str, $out);
}
echo '<hr />';
} else {
$str .= ((strlen($str)? ',': '')) . $arr;
$out .= ((strlen($out)? '<br />': '')) . $str;
}
return $out;
}
函数调用如下:
echo '<p>'.array2Rows($arr, '', '').'</p>';
这个函数的输出是:
- A,a,i,1
- A,a,i,j,2
- A,a,b,3
- A,B,a,m,4
- A,B,a,m,n,5
- A,B,a,b,6
除了第一个值之外,还有一个是不正确的,因为某些节点上的值是重复的。我已经尝试了递归函数的多种变体,这是我能得到的最接近的。
我将欢迎任何有关如何解决此问题的建议,如果问题的陈述不是很清楚,我深表歉意。
您重复倒数第二个值的原因是,在您的循环中,您在 运行 下一个数组的函数之前附加了键。这样的东西会更好:
function array2Rows($arr, &$out=[], $row = []) {
if (is_array($arr)) {
foreach ($arr as $key => $newArray) {
if (is_array($newArray)) {
$row[] = $key; //If the current value is an array, add its key to the current row
array2Rows($newArray, $out, $row); //process the new value
} else { //The current value is not an array
$out[] = implode(',',array_merge($row,[$key,$newArray])); //Add the current key and value to the row and write to the output
}
}
}
return $out;
}
这是轻微优化并利用参考来保存完整输出。我还将其更改为使用和 return 数组而不是字符串。我发现这两项更改都使函数更具可读性。
如果你想return一个格式类似于你函数中的字符串的字符串,请将最后一行替换为
return implode('<br>', $out);
或者,您可以在调用时执行此操作,这就是我所说的此类事情的“最佳实践”;例如
$result = array2Rows($arr);
echo implode('<br>', $result);
请注意,由于这使用了输出参考,因此这也有效:
array2Rows($arr, $result);
echo implode('<br>', $result);
你和你的函数太接近了……我把你的函数拿来稍微修改如下:
function array2Rows($arr, $str='', $csv='') {
$tmp = $str;
if (is_array($arr)) {
foreach ($arr as $att => $arr1) {
$tmp = $str . ((strlen($str)? ', ': '')) . $att;
$csv = array2Rows($arr1, $tmp, $csv);
}
} else {
$tmp .= ((strlen($str)? ', ': '')) . $arr;
$csv .= ((strlen($csv)? '<br />': '')) . $tmp;
}
return $csv;
}
唯一不同的是引入了一个临时变量$tmp,保证每次在递归函数运行之前不改变$str的值。
函数的输出变为:
这个功能不错,我可以想出几个应用程序。