我试图json_encode
debug_backtrace
输出用于将此信息存储在数据库中。如何删除递归?
问题是有时它包含递归。我不在乎的东西。在检测到递归的地方只需要*RECURSION*
就足够了。
我该怎么做?
我试图json_encode
debug_backtrace
输出用于将此信息存储在数据库中。如何删除递归?
问题是有时它包含递归。我不在乎的东西。在检测到递归的地方只需要*RECURSION*
就足够了。
我该怎么做?
序列化确实是一个很好的选择。
由于缺乏这一点,所以没有其他方法来遍历树,保留所有数组和对象,看看它们是否引用相同的值。
由于可以使用spl_object_hash,所以对象更容易一些。
对于数组,我现在能想到的唯一的办法就是以下
function referToTheSame(&$arr1, &$arr2) {
// copy
$tmp = $arr1;
$arr1 = 'foo';
$result = ($arr2==='foo');
$arr1 = $tmp;
return $result;
}
很想听到,如果有一个更聪明的方法。
哦,既然你只是想打破递归,而不是那么多任何参考这不会是那么昂贵。只需在遍历时保留一个堆栈,所以只需要与父母进行比较。
编辑
控制不住自己。这会中断数组引用,但不会引用对象。当然,你可以搞懂这个问题:
(警告:丑陋的代码)
<?php
$structure = array(
0 => 'foo',
1 => 'bar',
);
$structure[] =& $structure;
function traverse($item, &$stack) {
foreach($item as $key=>&$value) {
if (is_array($value)) {
// Checking if this array already appeared in the stack
foreach($stack as &$array2) {
// Copy
$tmp = $array2;
$array2 = 'foo';
if ($value==='foo') {
$array2 = $tmp;
// We need to create another temporary value, to break the
// reference.
$newValue = '* INCEPTION *';
$value =& $newValue;
continue 2;
} else {
$array2 = $tmp;
}
}
$stack[] =& $value;
traverse($value, $stack);
array_pop($stack);
}
}
}
$stack = array();
$stack =& $structure;
traverse($structure, $stack);
print_r($structure);
?>
我不认为它与循环函数有关。 debug_backtrace的输出仍然可以通过'object'和'args'键包含循环引用。 – Evert
我也有类似的问题我自己。我也用一个经过并删除了所有递归引用的函数来解决它。讽刺的是,这样做的功能本身就是递归的!这是我想出了:
public static function remove_recursion(&$object, &$stack = array()) {
if ((is_object($object) || is_array($object)) && $object) {
if (!in_array($object, $stack, true)) {
$stack[] = $object;
foreach ($object as &$subobject) {
self::remove_recursion($subobject, $stack);
}
} else {
$object = "***RECURSION***";
}
}
return $object;
}
对于第一个呼叫,你不需要在第二个参数来传递,这只是在那里它再次出现时。
纠正我,如果我错了,但它看起来像堆栈参数不应该通过引用传递在这里,因为它修改堆栈的所有层递归,而不是只有一个下层。 –
这是不正确的。您正在执行深度优先搜索,这会产生错误的输出 – Benubird
数据库值不需要编码为JSON。 – alex
使用序列化:) – Vyktor
嗯,我需要存储这些数据作为错误报告的一部分。我不关心关系,或者我应该说,我不想为追溯信息创建额外的2个表。 – Gajus