2009-12-02 7 views
1

에 대한 다차원 배열에서 경로 찾기이 같은 저장된 배열이 : 나는 특정 ID에 경로를 찾는 쉬운 방법을 찾기 위해 노력하고있어특정 ID

[0] => Array 
    (
     [id] => 1 
     [cat_name] => c1 
    ) 

[1] => Array 
    (
     [id] => 2 
     [cat_name] => c2 
     [copii] => Array 
      (
       [0] => Array 
        (
         [id] => 5 
         [cat_name] => c21 
        ) 

       [1] => Array 
        (
         [id] => 6 
         [cat_name] => c22 
        ) 

      ) 

    ) 

[2] => Array 
    (
     [id] => 3 
     [cat_name] => c3 
     [copii] => Array 
      (
       [0] => Array 
        (
         [id] => 7 
         [cat_name] => c31 
         [copii] => Array 
          (
           [0] => Array 
            (
             [id] => 9 
             [cat_name] => c311 
            ) 

          ) 

        ) 

       [1] => Array 
        (
         [id] => 8 
         [cat_name] => c32 
        ) 

      ) 

    ) 

합니다. 이제 foreach를 사용하여 가능한 모든 배열을 반복하고 경로를 찾습니다.

예 : 내 질문에 아무 의미

id = 1: 
    route[0][id]=1,route[0][cat_name]=c1 
id = 5: 
    route[0][id]=2,route[0][cat_name]=c2 
    route[1][id]=5,route[1][cat_name]=c21 
id = 9: 
    route[0][id]=3,route[0][cat_name]=c3 
    route[1][id]=7,route[1][cat_name]=c31 
    route[2][id]=9,route[2][cat_name]=c311 

경우에, 나는

답변

1

많은 코드를 게시하는 대신, 알지 못하면 재귀에 대해 읽어 보시기 바랍니다. PHP는 재귀에서 너무 뛰어나지는 않지만 실제로 유일한 옵션입니다.

기본적으로 찾으려는 배열 id와 경로를 나타내는 문자열/배열을 호출합니다. 처음에는 빈 문자열 또는 빈 배열을 사용하여 후자의 매개 변수를 호출하십시오.

  • 실행 $array
  • 의 최상위 레벨을 통해 foreach는 당신이 $id 당신이 $path 반환을 찾고 찾을 경우 :이 작업을 수행 할 기능에

    .
  • 배열 값 중 하나가 하위 배열 인 경우 현재 ID 노드를 추가하고 해당 함수를 다시 호출합니다 (예 : $foundPath = findPath($array, $id, $path)).
  • $foundPath이 무언가를 반환하면 경로가 생겨 반환 될 수 있습니다.
  • 아무 것도 찾지 못했다면 ($foundPath은 false 또는 null입니다.) 그대로두고 루프의 다음 반복으로 넘어갑니다.
  • 루프의 끝에서 아무것도 찾지 못하면 false 또는 null을 반환합니다.

희망 하시겠습니까?

+0

재귀 알고리즘을 피하기 위해 노력하고 있습니다. 그 (것)들에 대해 알고 있지만, 사용하려고합니다. iterative solution ... 만약 내가 할 수 없다면, 재귀 적으로 멈추지 만 첫 번째 옵션이 아니다. – Raz

+0

배열의 깊이가 알려지지 않았다면 재귀가 유일한 해결책이다. 절대로 3 열 이상의 배열이 아니더라도 재귀는 여러 중첩 루프보다 더 깨끗한 코드입니다. – DisgruntledGoat

+0

최대 깊이가 3입니다. 이제 재귀 및 반복 솔루션의 효율성을 테스트하고 있습니다 ... 오늘 나중에 솔루션으로 질문을 업데이트하겠습니다. – Raz

0

귀하의 질문은 참으로 말도 안돼 ... 그것에 대한 좋은 해결책을 찾기 위해 노력하고 소요되는 시간에 그것을 비난. "경로 찾기"는 무엇을 의미합니까?

배열에 그래프를 설명하는 재귀 적 구조가있는 것 같습니다. 최단 경로를 찾는 그래프 탐색 알고리즘이 더 적절할 수 있습니다 (즉, 배열을 그래프 데이터 구조 (노드 목록 + 가장자리 목록)로 변환하고 그래프 그래프를 실행하십시오.

+0

그래, 그래프처럼 구조화되어 있지만 구조를 변경하지 않으려 고합니다. – Raz

1

재귀는 당신이 원하는 무엇인가 :

<?php 

    function walk_array(array $a, &$ra, $path, $depth = 0) { 
    $id= isset($path[$depth]) ? $path[$depth] : null; 
    if (!is_null($id)) { 
     foreach ($a as $a2) { 
     if ($a2['id'] == $id) { 
     $ra[$depth]= $a2; 
     unset($ra[$depth]['copii']); 
     // This is the key bit - recursion is simply a function calling itself: 
     if (isset($a2['copii'])) 
     walk_array($a2['copii'], $ra, $path, ++$depth); 
     } 
     } 
    } 
    } 

    $complex_array= array(
     array('id'=> 1, 'name'=> 'Node #1', 'copii'=> array(
     array('id'=> 3, 'name'=> 'Node #3', 'copii'=> array(
     array('id'=> 4, 'name'=> 'Node #4') 
     )) 
    )), 
     array('id'=> 2, 'name'=> 'Node #2', 'copii'=> array(
     array('id'=> 5, 'name'=> 'Node #5', 'copii'=> array(
     array('id'=> 6, 'name'=> 'Node #6',) 
     )) 
    )), 
    );  

    // Prints out nodes 1,3,4 in order 
    $ra= array(); 
    walk_array($complex_array, $ra, array(1, 3, 4)); 
    print_r($ra); 

    // Prints out nodes 2,5,6 in order 
    $ra= array(); 
    walk_array($complex_array, $ra, array(2, 5, 6)); 
    print_r($ra); 

    // Prints out empty array 
    $ra= array(); 
    walk_array($complex_array, $ra, array(5, 2, 4)); 
    print_r($ra); 

    // Prints out nodes 2,5 in order 
    $ra= array(); 
    walk_array($complex_array, $ra, array(2, 5)); 
    print_r($ra); 
?> 
+0

재귀,하지만 지금까지 내가 PHP에서 본 것이 최선의 해결책이 아니므로, 나는 그것을 피하려고합니다. – Raz

0
내가 생각할 수있는 또 다른 방법

- 피 재귀 - 당신은 단지까지, 배열 인덱스의 가능한 모든 조합을 시도 그래서, "변수 변수"를 사용하는 것입니다 포인트.

$search = 3; 
$ind = '$arr[0][copii][1]'; // generated somehow 
if (isset(${$ind}['id']) && ${$ind}['id'] == $search) { 
    // we found it 
} 

이렇게 오래 걸릴 것이므로 아무 것도 찾을 수 없습니다. 또한이 글을 쓰면서 나는 재귀와 별도로 $ind 개의 값을 생성하는 견고한 방법에 대해 고심하고있다. 나는 당신이 000, 001, 002와 같은 3 자리 숫자를 생성하고 $arr[0][copii][0][copii][0], $arr[0][copii][0][copii][1]$arr[0][copii][0][copii][2]과 같은 색인을 생성하기 위해 각 문자를 사용할 수 있다고 생각합니다.

의심 할 여지없이 값을 놓치고 존재하지 않는 많은 값을 찾을 것이기 때문에이 방법은 여전히 ​​완벽하지 않습니다. 솔직히 말하면, 재귀는 코드에 따라 더 간단하고 깨끗한 옵션이며 배열에 수백 개의 항목이 없으면 큰 성능 문제가 발생하지 않을 것입니다.

관련 문제