我正在编写一个函数来从胡子模板中获取标签并生成哈希(这样做的原因是能够获取任何给定的模板并快速向开发人员显示预期变量是什么)。
我将标签提取到平面数组中(很容易),但下一步很棘手 - 我需要将平面数组转换为多维数组以指示嵌套变量。
这是我的样本平面阵列:
$arr = array(
'one',
'#two',
'sub1',
'sub2',
'/two',
'three'
);
预期的产出:
$newArray = array(
'one'=>'',
'two'=>array(
'sub1'=>'',
'sub2'=>''
),
'three'=>''
);
我已经越来越近了,但还没到那儿。我认为递归函数是可行的方法(尽管我对另一种解决方案持开放态度)。以下是我到目前为止的情况:
function recurse($array, $i = 0) {
$nested = array();
while ($i < count($array)):
$tag = $array[$i];
if (preg_match('/\//',$tag)) {
return $nested;
} elseif (preg_match('/^#/',$tag)) {
$tag = str_replace('#','',$tag);
$nested[$tag] = recurse($array, $i+1);
$i+= count($nested[$tag])+1;
} else {
$nested[$tag] = '';
$i++;
}
endwhile;
return $nested;
}
我认为错误可能是它击中了第一个'if'并且一直返回函数,但我不确定,也不确定如何解决它。
答案 0 :(得分:3)
为了好玩,我决定让你一个没有递归并使用引用(更有效的递归,在堆栈上存储数组元素别名)。也适用于嵌套子集。
$arr = array(
'one',
'#two','sub1',
'#twotwo','sub1','sub2','/twotwo',
'sub2','/two',
'three'
);
$out = array();
$stack = array();
$sp = 0;
$stack[$sp] = &$out;
foreach ($arr as $item) {
$cur =& $stack[$sp];
if ($item[0] == '#') {
$item = substr($item, 1);
$cur[$item] = array();
$stack[++$sp] = &$cur[$item];
}
elseif ($item[0] == '/') {
$sp--;
}
else {
$cur[] = $item;
}
}
var_dump($out);
输出:
array
0 => string 'one' (length=3)
'two' => &
array
0 => string 'sub1' (length=4)
'twotwo' => &
array
0 => string 'sub1' (length=4)
1 => string 'sub2' (length=4)
1 => string 'sub2' (length=4)
1 => string 'three' (length=5)
您可以在地方& array
中忽略输出中的事实,而不仅仅是array
。这表示在符号表中该特定元素的引用计数是> 1。
原因是$stack
仍在维护引用。如果在返回输出之前执行unset($stack);
,则会删除其他引用,并且输出中的&
将消失。
答案 1 :(得分:2)
这可能是你正在寻找的更多(并且更接近真正的递归),但我没有测试它,因为我现在没有PHP实例可以解决
用法:
$input = array(
'one',
'#two',
'sub1',
'sub2',
'/two',
'three'
);
$result = array();
recurse($input, $result, '', 0);
步骤:
代码:
function recurse($input, &$result, $tag, $position)
{
if($position >= count($input))
{
return;
}
if(preg_match('@\/@',$input[$position]))
{
recurse($input, $result, '', $position + 1);
}
else if (preg_match('@^#@',$input[$position]))
{
$result[substr($input[$position], 1)] = array();
recurse($input, $result, substr($input[$position], 1), $position + 1);
}
else if($tag == '')
{
$result[$input[$position]] = '';
recurse($input, $result, $tag, $position + 1);
}
else
{
$result[$tag][$input[$position]] = '';
recurse($input, $result, $tag, $position + 1);
}
}
答案 2 :(得分:2)
我根据您的需要修改了您的功能,看看它是否适合您:
$arr = array(
'one',
'#two',
'sub1',
'#sub2',
'subsub1',
'subsub2',
'subsub3',
'subsub4',
'/sub2',
'sub3',
'/two',
'three'
);
function recurse($array, &$i, $current_tag = "")
{
$nested = array();
while ($i < count($array)):
$tag = $array[$i];
if ($tag == '/'.$current_tag)
{
$i++;
return $nested;
}
elseif (preg_match('/^#/',$tag))
{
$tag = str_replace('#','',$tag);
$i++;
$nested[$tag] = recurse($array, $i, $tag);
} else
{
$nested[$tag] = '';
$i++;
}
endwhile;
return $nested;
}
$i = 0;
$a = recurse($arr, $i);
echo '<pre>'.print_r($a, true).'</pre>';
你对这个$ i有一些问题...我把它作为参考,以便它会自动用功能系统更新,并使用另一个参数来准确匹配下一个结束标签......,这样它就会验证
答案 3 :(得分:2)
是的,recurse功能就是这样。一些建议:
这是另一种做你想做的事情:
<?php
function recurse(&$array, &$return = array(), &$i = 0, $limit = NULL)
{
if(!isset($limit)){
$limit = count($array) ;
}
for(;$i < $limit;$i++){
if($array[$i]{0} == '#'){
//opening
$key = substr($array[$i++], 1) ;
$return[$key] = array();
recurse($array, $return[$key], $i, $limit) ;
}elseif($array[$i]{0} == '/'){
return ;
}else{
//same level
$return[$array[$i]] = '';
}
}
}
$arr = array(
'one',
'#two',
'sub1',
'#t2',
'sub1.1',
'sub1.2',
'/t2',
'sub2',
'/two',
'three'
);
$nested = array();
recurse($arr, $nested);
var_dump($nested);
?>
答案 4 :(得分:1)
关闭一个错误
$tag = str_replace('#','',$tag);
$nested[$tag] = recurse($array, $i+1);
$i+= count($nested[$tag])+1;
当您返回嵌套数组时,您必须跳过结束标记,因此它应该是$i += count($nested[$tag]) + 2;
。