我試圖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