2012-06-28 48 views
9

thể trùng lặp:
Converting an array from one to multi-dimensional based on parent ID valuesPHP Tạo một mảng đa chiều từ một mảng với dữ liệu quan hệ

Tôi đang làm việc trong PHP.

Tôi có mảng sau có dữ liệu quan hệ (mối quan hệ con mẹ).

Array   
(  
    [5273] => Array   
     (  
      [id] => 5273   
      [name] => John Doe   
      [parent] =>   
     )   

    [6032] => Array   
     (  
      [id] => 6032   
      [name] => Sally Smith   
      [parent] => 5273   
     )   

    [6034] => Array   
     (  
      [id] => 6034   
      [name] => Mike Jones   
      [parent] => 6032   
     )   

    [6035] => Array   
     (  
      [id] => 6035   
      [name] => Jason Williams   
      [parent] => 6034   
     )   

    [6036] => Array   
     (  
      [id] => 6036   
      [name] => Sara Johnson   
      [parent] => 5273   
     )   

    [6037] => Array   
     (  
      [id] => 6037   
      [name] => Dave Wilson   
      [parent] => 5273   
     )   

    [6038] => Array   
     (  
      [id] => 6038   
      [name] => Amy Martin   
      [parent] => 6037   
     )   
)   

tôi cần nó phải ở định dạng JSON này:

{   
    "id":"5273",   
    "name":"John Doe",   
    "data":{   

    },   
    "children":[   
     {   
     "id":" Sally Smith",   
     "name":"6032",   
     "data":{   

     },   
     "children":[   
      {   
       "id":"6034",   
       "name":"Mike Jones",   
       "data":{   

       },   
       "children":[   
        {   
        "id":"6035",   
        "name":"Jason Williams",   
        "data":{   

        },   
        "children":[   
         {   
          "id":"node46",   
          "name":"4.6",   
          "data":{   

          },   
          "children":[   

          ]   
         }   
        ]   
        }   
       ]   
      },   
      {   
       "id":"6036",   
       "name":"Sara Johnson",   
       "data":{   

       },   
       "children":[   

       ]   
      },   
      {   
       "id":"6037",   
       "name":"Dave Wilson",   
       "data":{   

       },   
       "children":[   
        {   
        "id":"6038",   
        "name":"Amy Martin",   
        "data":{   

        },   
        "children":[   

        ]   
        }   
       ]   
      }   
     ]   
     }   
    ]   
}   

Tôi biết tôi cần phải tạo ra một mảng đa chiều và chạy nó thông qua json_encode(). Tôi cũng tin rằng phương pháp này được sử dụng để làm điều này cần phải được đệ quy bởi vì dữ liệu thế giới thực có thể có một số lượng không rõ các cấp.

Tôi rất vui khi hiển thị một số phương pháp tiếp cận của tôi nhưng chúng không hoạt động.

Có ai có thể giúp tôi không?

Tôi được yêu cầu chia sẻ công việc của mình. Đây là những gì tôi đã thử nhưng tôi đã không nhận được rằng gần gũi với tôi không biết làm thế nào nó là hữu ích.

Tôi đã tạo một mảng chỉ là các mối quan hệ.

foreach($array as $k => $v){ 
    $relationships[$v['id']] = $v['parent']; 
} 

Tôi nghĩ (dựa trên một bài đăng SO khác) đã sử dụng dữ liệu quan hệ này để tạo mảng đa chiều mới. Nếu tôi làm việc này, tôi sẽ làm việc để thêm nhãn "trẻ em" chính xác, v.v.

$childrenTable = array(); 
    $data = array(); 
    foreach ($relationships as $n => $p) { 
     //parent was not seen before, put on root 
     if (!array_key_exists($p, $childrenTable)) { 
      $childrenTable[$p] = array(); 
      $data[$p] = &$childrenTable[$p]; 
     } 
     //child was not seen before 
     if (!array_key_exists($n, $childrenTable)) { 
      $childrenTable[$n] = array(); 
     } 
     //root node has a parent after all, relocate 
     if (array_key_exists($n, $data)) { 
      unset($data[$n]); 
     } 
     $childrenTable[$p][$n] = &$childrenTable[$n];  
    } 
    unset($childrenTable); 

print_r($data); 
+0

Định dạng ban đầu bạn đăng * là * một mảng đa chiều. Không nên làm việc trong mã hóa json? –

+0

Ben Roux, Vâng, đó là một mảng đa chiều nhưng nó không có định dạng đúng để tạo ra JSON đó. – maestrojed

+0

những gì bạn đã thử? đăng mã của bạn như thế nào bạn đang chuẩn bị mảng. – Sanjay

Trả lời

12
<?php 
header('Content-Type: application/json; charset="utf-8"'); 

/** 
* Helper function 
* 
* @param array $d flat data, implementing a id/parent id (adjacency list) structure 
* @param mixed $r root id, node to return 
* @param string $pk parent id index 
* @param string $k id index 
* @param string $c children index 
* @return array 
*/ 
function makeRecursive($d, $r = 0, $pk = 'parent', $k = 'id', $c = 'children') { 
    $m = array(); 
    foreach ($d as $e) { 
    isset($m[$e[$pk]]) ?: $m[$e[$pk]] = array(); 
    isset($m[$e[$k]]) ?: $m[$e[$k]] = array(); 
    $m[$e[$pk]][] = array_merge($e, array($c => &$m[$e[$k]])); 
    } 

    return $m[$r][0]; // remove [0] if there could be more than one root nodes 
} 

echo json_encode(makeRecursive(array(
    array('id' => 5273, 'parent' => 0, 'name' => 'John Doe'), 
    array('id' => 6032, 'parent' => 5273, 'name' => 'Sally Smith'), 
    array('id' => 6034, 'parent' => 6032, 'name' => 'Mike Jones'), 
    array('id' => 6035, 'parent' => 6034, 'name' => 'Jason Williams'), 
    array('id' => 6036, 'parent' => 5273, 'name' => 'Sara Johnson'), 
    array('id' => 6037, 'parent' => 5273, 'name' => 'Dave Wilson'), 
    array('id' => 6038, 'parent' => 6037, 'name' => 'Amy Martin'), 
))); 

demo: https://3v4l.org/s2PNC

+0

Yoshi, Cảm ơn bạn. Tôi chạy mã của bạn chống lại các thử nghiệm và nó làm việc tuyệt vời. Tuy nhiên khi tôi thực hiện một số dữ liệu thực tế có thể là 300-400 người. Tôi nhận được một lỗi 128MB PHP bị lỗi. Tôi hiểu 300-400 hồ sơ là nhiều hơn thì ví dụ tôi cung cấp nhưng tôi không nghĩ rằng nó sẽ được coi là một tập dữ liệu lớn. Bất kỳ ý tưởng? Liệu nó có ý nghĩa rằng điều này sử dụng nhiều bộ nhớ như vậy? – maestrojed

+0

@maestrojed Đã xảy ra lỗi trong phiên bản đầu tiên của tôi (có thể là nguyên nhân gây ra rò rỉ bộ nhớ), vui lòng xem bản cập nhật. – Yoshi

+1

Điều đó đã hiệu quả và nhiều hơn tôi mong đợi. Cảm ơn đã giúp đỡ. Tôi mong được phân tích nó và học một cái gì đó! – maestrojed

2

Mã sau đây sẽ thực hiện công việc .. bạn có thể muốn chỉnh sửa một chút theo nhu cầu của mình.

$data = array(
    '5273' => array('id' =>5273, 'name'=> 'John Doe', 'parent'=>''), 
    '6032' => array('id' =>6032, 'name'=> 'Sally Smith', 'parent'=>'5273'), 
    '6034' => array('id' =>6034, 'name'=> 'Mike Jones ', 'parent'=>'6032'), 
    '6035' => array('id' =>6035, 'name'=> 'Jason Williams', 'parent'=>'6034') 
    ); 

$fdata = array(); 


function ConvertToMulti($data) { 
    global $fdata; 

    foreach($data as $k => $v) 
    { 
     if(empty($v['parent'])){ 
      unset($v['parent']); 
     $v['data'] = array(); 
     $v['children'] = array(); 
      $fdata[] = $v; 
     } 
     else { 
      findParentAndInsert($v, $fdata); 
     } 

    } 
} 

function findParentAndInsert($idata, &$ldata) { 

    foreach ($ldata as $k=>$v) { 

     if($ldata[$k]['id'] == $idata['parent']) { 
      unset($idata['parent']); 
     $idata['data'] = array(); 
     $idata['children'] = array(); 
      $ldata[$k]['children'][] = $idata; 
      return; 
     } 
     else if(!empty($v['children'])) 
      findParentAndInsert($idata, $ldata[$k]['children']); 
    } 
} 


print_r($data); 
ConvertToMulti($data); 
echo "AFTER\n"; 
print_r($fdata); 

http://codepad.viper-7.com/Q5Buaz

+0

Tôi sẽ tiếp tục cố gắng này vào buổi sáng. Ngày đầu tiên thực hiện nó dường như có vấn đề. Tôi không chắc chắn những gì được nêu ra và sẽ cố gắng bình luận trở lại với các chi tiết. Khi tôi thực hiện nó tôi không nhận được một lỗi và cấu trúc có vẻ đúng nhưng rất nhiều dữ liệu bị thiếu. – maestrojed

+0

Xin lưu ý một vài điều, Thứ nhất, Điền vào mảng dữ liệu $ với của bạn. Nó không có tất cả các giá trị bạn đã sử dụng trong câu hỏi. Thứ hai, bạn có thể làm cho $ fdata địa phương để ConvertToMulti chức năng. Làm cho nó toàn cầu có thể gây ra vấn đề trong việc thực hiện của bạn. Chúc may mắn với việc thực hiện của bạn – FatalError

3

Được rồi, đây là cách nó hoạt động, bạn đã thực sự không phải là quá xa như bạn bắt đầu, nhưng những gì bạn thực sự tìm kiếm là tài liệu tham khảo. Đây là thủ tục chung:

Vì có mối quan hệ giữa nút cha và nút con trên ID của chúng, trước tiên bạn cần lập chỉ mục dữ liệu dựa trên ID. Tôi làm điều này ở đây với một mảng ($rows) để mô phỏng truy cập dữ liệu của bạn, nếu bạn đọc từ cơ sở dữ liệu, nó sẽ là tương tự. Với lập chỉ mục này, bạn cũng có thể thêm các thuộc tính bổ sung như dữ liệu rỗng của bạn:

// create an index on id 
$index = array(); 
foreach($rows as $row) 
{ 
    $row['data'] = (object) array(); 
    $index[$row['id']] = $row; 
} 

Vì vậy, bây giờ tất cả các mục được lập chỉ mục trên ID của họ. Đây là bước đầu tiên.

Bước thứ hai cũng không kém phần quan trọng. Bởi vì bây giờ chúng ta có thể truy cập mỗi nút dựa trên ID của nó trong $index, chúng ta có thể gán các con cho cha mẹ của chúng.

Có một nút "ảo", đó là nút có ID 0.Nó không tồn tại trong bất kỳ hàng nào, tuy nhiên, nếu chúng ta có thể thêm con vào nó, chúng ta có thể sử dụng bộ sưu tập con này làm cửa hàng cho tất cả các nút gốc, trong trường hợp của bạn, có một nút gốc đơn.

Chắc chắn, đối với ID 0, chúng tôi không nên xử lý cấp độ gốc - bởi vì nó không tồn tại.

Vì vậy, hãy làm điều đó. Chúng tôi tận dụng tài liệu tham khảo ở đây bởi vì nếu không cùng một nút không thể được cả hai cha mẹ và con:

// build the tree 
foreach($index as $id => &$row) 
{ 
    if ($id === 0) continue; 
    $parent = $row['parent']; 
    $index[$parent]['children'][] = &$row; 
} 
unset($row); 

Bởi vì chúng ta sử dụng tài liệu tham khảo, dòng cuối cùng sẽ chăm sóc để bỏ đặt tham chiếu được lưu trữ trong $row sau vòng lặp.

Bây giờ tất cả trẻ em đã được chỉ định cho cha mẹ của chúng. Điều đó có thể nó đã được, tuy nhiên cho phép không quên bước cuối cùng, các nút thực tế cho đầu ra nên được truy cập.

Để ngắn gọn, chỉ cần gán nút gốc cho chính số $index. Nếu chúng ta nhớ, các nút gốc duy nhất chúng tôi muốn là người đầu tiên trong mảng trẻ em trong nút với ID 0:

// obtain root node 
$index = $index[0]['children'][0]; 

Và đó là nó. Chúng ta có thể sử dụng nó bây giờ ngay lập tức để tạo ra JSON:

// output json 
header('Content-Type: application/json'); 
echo json_encode($index); 

Cuối cùng toàn bộ mã trong nháy mắt:

<?php 
/** 
* @link http://stackoverflow.com/questions/11239652/php-create-a-multidimensional-array-from-an-array-with-relational-data 
*/ 

$rows = array(
    array('id' => 5273, 'parent' => 0, 'name' => 'John Doe'), 
    array('id' => 6032, 'parent' => 5273, 'name' => 'Sally Smith'), 
    array('id' => 6034, 'parent' => 6032, 'name' => 'Mike Jones'), 
    array('id' => 6035, 'parent' => 6034, 'name' => 'Jason Williams'), 
    array('id' => 6036, 'parent' => 5273, 'name' => 'Sara Johnson'), 
    array('id' => 6037, 'parent' => 5273, 'name' => 'Dave Wilson'), 
    array('id' => 6038, 'parent' => 6037, 'name' => 'Amy Martin'), 
); 

// create an index on id 
$index = array(); 
foreach($rows as $row) 
{ 
    $row['data'] = (object) []; 
    $index[$row['id']] = $row; 
} 

// build the tree 
foreach($index as $id => &$row) 
{ 
    if ($id === 0) continue; 
    $parent = $row['parent']; 
    $index[$parent]['children'][] = &$row; 
} 
unset($row); 

// obtain root node 
$index = $index[0]['children'][0]; 

// output json 
header('Content-Type: application/json'); 
echo json_encode($index, JSON_PRETTY_PRINT); 

nào sẽ tạo ra json sau (ở đây với PHP 5.4s' JSON_PRETTY_PRINT):

{ 
    "id": 5273, 
    "parent": 0, 
    "name": "John Doe", 
    "data": { 

    }, 
    "children": [ 
     { 
      "id": 6032, 
      "parent": 5273, 
      "name": "Sally Smith", 
      "data": { 

      }, 
      "children": [ 
       { 
        "id": 6034, 
        "parent": 6032, 
        "name": "Mike Jones", 
        "data": { 

        }, 
        "children": [ 
         { 
          "id": 6035, 
          "parent": 6034, 
          "name": "Jason Williams", 
          "data": { 

          } 
         } 
        ] 
       } 
      ] 
     }, 
     { 
      "id": 6036, 
      "parent": 5273, 
      "name": "Sara Johnson", 
      "data": { 

      } 
     }, 
     { 
      "id": 6037, 
      "parent": 5273, 
      "name": "Dave Wilson", 
      "data": { 

      }, 
      "children": [ 
       { 
        "id": 6038, 
        "parent": 6037, 
        "name": "Amy Martin", 
        "data": { 

        } 
       } 
      ] 
     } 
    ] 
} 
+0

Bạn có thể giải thích những gì không được đặt ($ row); đang thực hiện –

+0

@LovepreetSinghBatth: Đó là "Bởi vì chúng tôi sử dụng tài liệu tham khảo, dòng cuối cùng chú ý để bỏ đặt tham chiếu được lưu trữ trong hàng $ sau vòng lặp". bên dưới ví dụ. – hakre

Các vấn đề liên quan