2012-01-28 6 views
14

tôi vừa làm lại thuật toán phát hiện đệ quy của tôi trong con vật cưng dump_r dự án của tôi()phát hiện đệ quy mảng vô hạn trong PHP?

https://github.com/leeoniya/dump_r.php

phát hiện đối tượng đệ quy không phải là quá khó khăn - bạn sử dụng spl_object_hash() để lấy id nội bộ độc đáo của các trường hợp đối tượng , lưu trữ nó trong một dict và so sánh với nó trong khi bán phá giá các nút khác.

để phát hiện đệ quy mảng, tôi hơi bối rối, tôi không thấy bất kỳ điều gì hữu ích. php chính nó có thể xác định đệ quy, mặc dù nó dường như làm điều đó một chu kỳ quá muộn. EDIT: nvm, nó xảy ra nơi nó cần phải :)

$arr = array(); 
$arr[] = array(&$arr); 
print_r($arr); 

nó phải nghỉ mát để theo dõi tất cả mọi thứ trong đệ quy stack và làm so sánh nông chống lại mọi phần tử mảng khác?

bất kỳ trợ giúp nào sẽ được đánh giá cao,
cảm ơn!

+0

lol - eeewwwww. – leeoniya

+1

Không phải là câu trả lời cho quesiton của bạn nhưng tôi đã thấy các giải pháp kiểm tra 'print_r ($ var, true)' cho chuỗi chỉ ra đệ quy. Điều này là về khó chịu như bạn có thể nhận được nhưng hoạt động ... Xem [ở đây] (http://noteslog.com/post/detecting-recursive-dependencies-in-php-composite-values/) cho một thỏa hiệp khá. – Basic

+0

Tôi đã xóa/chỉnh sửa nhận xét của mình để chứa liên kết đến một ví dụ nhưng tôi đồng ý, nó stinks – Basic

Trả lời

9

Bởi vì cơ chế gọi-by-value của PHP, giải pháp duy nhất tôi nhìn thấy ở đây là để lặp mảng bằng cách tham khảo, và thiết lập một giá trị tùy ý trong nó, mà bạn sau đó kiểm tra nếu nó tồn tại để tìm hiểu xem bạn đã có trước đây:

function iterate_array(&$arr){ 

    if(!is_array($arr)){ 
    print $arr; 
    return; 
    } 

    // if this key is present, it means you already walked this array 
    if(isset($arr['__been_here'])){ 
    print 'RECURSION'; 
    return; 
    } 

    $arr['__been_here'] = true; 

    foreach($arr as $key => &$value){ 

    // print your values here, or do your stuff 
    if($key !== '__been_here'){ 
     if(is_array($value)){ 
     iterate_array($value); 
     } 

     print $value; 
    } 
    } 

    // you need to unset it when done because you're working with a reference... 
    unset($arr['__been_here']); 

} 

bạn có thể quấn chức năng này vào một chức năng chấp nhận giá trị thay vì tài liệu tham khảo, nhưng sau đó bạn sẽ nhận được thông báo đệ quy từ cấp 2 trên. Tôi nghĩ print_r cũng vậy.

+0

** this ** là giải pháp tôi đã hy vọng - đơn giản và tuyệt vời. – leeoniya

3

Ai đó sẽ sửa tôi nếu tôi sai, nhưng PHP thực sự đang phát hiện đệ quy vào đúng thời điểm. Nhiệm vụ của bạn chỉ đơn giản là tạo ra chu kỳ bổ sung. Ví dụ nên là:

$arr = array(); 
$arr = array(&$arr); 

Mà sẽ dẫn đến

array(1) { [0]=> &array(1) { [0]=> *RECURSION* } } 

Đúng như dự đoán.


Vâng, tôi hơi tò mò về cách phát hiện đệ quy và tôi bắt đầu với Google. Tôi thấy bài viết này http://noteslog.com/post/detecting-recursive-dependencies-in-php-composite-values/ và giải pháp này:

function hasRecursiveDependency($value) 
{ 
    //if PHP detects recursion in a $value, then a printed $value 
    //will contain at least one match for the pattern /\*RECURSION\*/ 
    $printed = print_r($value, true); 
    $recursionMetaUser = preg_match_all('@\*RECURSION\*@', $printed, $matches); 
    if ($recursionMetaUser == 0) 
    { 
     return false; 
    } 
    //if PHP detects recursion in a $value, then a serialized $value 
    //will contain matches for the pattern /\*RECURSION\*/ never because 
    //of metadata of the serialized $value, but only because of user data 
    $serialized = serialize($value); 
    $recursionUser = preg_match_all('@\*RECURSION\*@', $serialized, $matches); 
    //all the matches that are user data instead of metadata of the 
    //printed $value must be ignored 
    $result = $recursionMetaUser > $recursionUser; 
    return $result; 
} 
+0

bạn nói đúng. nó không muộn. nhưng tôi vẫn cần một cách để làm điều này bên ngoài chức năng gốc. – leeoniya

+0

tốt, giải pháp này không chính xác những gì tôi đã hy vọng vì nó là cực kỳ đánh thuế trên các cấu trúc lớn và dựa trên một print_r() hoặc serialize không thể kiểm soát nội bộ, là một phần của lý do tôi bắt đầu dự án để bắt đầu, heh , nhưng http://www.phpsadness.com/ :( – leeoniya