2012-06-28 13 views
9

Duplicar posibles:
Converting an array from one to multi-dimensional based on parent ID valuesPHP crear una matriz multidimensional de una matriz con datos relacionales

estoy trabajando en PHP.

Tengo la siguiente matriz que tiene datos relacionales (relaciones primarias secundarias).

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   
     )   
)   

necesito que sea en este formato JSON:

{   
    "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":[   

        ]   
        }   
       ]   
      }   
     ]   
     }   
    ]   
}   

Sé que necesito para crear una matriz multidimensional y ejecutarlo a través json_encode(). También creo que este método utilizado para hacer esto debe ser recursivo porque los datos del mundo real podrían tener un número desconocido de niveles.

Estaría encantado de mostrar algunos de mis enfoques, pero no han funcionado.

¿Alguien me puede ayudar?

Me pidieron que compartiera mi trabajo. Esto es lo que he intentado, pero no me he acercado tanto a él que no sé lo útil que es.

Hice una serie de solo las relaciones.

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

Creo que (basado en otra publicación SO) usé estos datos relacionales para crear una nueva matriz multidimensional. Si tengo que esto funcione iba a trabajar en la adición de las etiquetas correctas "niños" etc.

$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

El formato inicial que publicó * es * una matriz multidimensional. ¿No debería funcionar eso en json? –

+0

Ben Roux, sí, es una matriz multidimensional pero no está en el formato correcto para producir esa JSON. – maestrojed

+0

¿Qué has intentado? publique su código de cómo está preparando la matriz. – Sanjay

Respuesta

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, gracias. Ejecuté tu código en contra de la prueba y funciona muy bien. Sin embargo, cuando implementé algunos datos del mundo real, puede haber entre 300 y 400 personas. Obtengo un PHP agotado de 128mb de error de memoria. Entiendo que 300-400 registros es más que el ejemplo que proporcioné, pero no creo que se considere un gran conjunto de datos. ¿Algunas ideas? ¿Tiene sentido que esto usó tanta memoria? – maestrojed

+0

@maestrojed Hubo un error en mi primera versión (probablemente la causa de la pérdida de memoria), eche un vistazo a la actualización. – Yoshi

+1

Eso funcionó y fue más de lo que esperaba. Gracias por la ayuda. ¡Espero con ansias analizarlo y aprender algo! – maestrojed

2

siguiente código hará el trabajo .. es posible que desee ajustar un poco de acuerdo a sus necesidades.

$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

Voy a seguir intentándolo por la mañana. En la primera implementación, parecía tener problemas. Todavía no estoy seguro de qué y trataré de comentar con detalles. Cuando lo implementé, no obtuve un error y la estructura parece correcta, pero faltan muchos datos. – maestrojed

+0

Tenga en cuenta un par de cosas, en primer lugar, llene la matriz $ data con la suya. No tiene todos los valores que usaste en la pregunta. En segundo lugar, puede hacer que la función $ fdata local funcione en ConvertToMulti. Hacerlo global puede causar problemas en su implementación. Buena suerte con su implementación – FatalError

3

autorización, ésta es la forma en que funciona, que eran en realidad no está demasiado lejos como empezar, pero lo que realmente busca son referencias. Este es un procedimiento general:

Como existe una relación entre el padre y los nodos hijos en su ID, primero debe indizar los datos en función de la ID. Hago esto aquí con una matriz ($rows) para simular su acceso a los datos, si lee de la base de datos, sería similar. Con esta indexación también se puede añadir propiedades adicionales como sus datos vacía:

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

Así que ahora todas las entradas están indexados en su identificación. Este fue el primer paso.

El segundo paso es igualmente directo. Como ahora podemos acceder a cada nodo según su ID en el $index, podemos asignar los elementos secundarios a su elemento primario.

Hay un nodo "virtual", que es el que tiene el ID 0.No existe en ninguna de las filas, sin embargo, si también pudiéramos agregarle elementos secundarios, podemos usar esta colección secundaria como la tienda para todos los nodos raíz, en su caso, hay un único nodo raíz.

Claro, para el ID 0, no deberíamos procesar el elemento primario porque no existe.

Así que hagámoslo. Hacemos uso de las referencias aquí porque de lo contrario el mismo nodo no podía ser padres e hijos:

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

Debido a que usamos referencias, la última línea se encarga de desarmar la referencia almacenada en $row después del bucle.

Ahora todos los niños han sido asignados a sus padres. Eso podría ser ya, pero no olvidemos el último paso, se debe acceder al nodo real para la salida.

Para abreviar, simplemente asigne el nodo raíz al $index. Si recordamos, el único nodo raíz que queremos es el primero en la matriz de los niños en el nodo con el ID 0:

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

Y eso es todo. Podemos usarlo ahora de inmediato para generar el JSON:

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

Finalmente todo el código de un vistazo:

<?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); 

que crearía el siguiente JSON (aquí con 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

¿Puede explicar qué unset ($ row); está haciendo –

+0

@LovepreetSinghBatth: Es "Como usamos referencias, la última línea se encarga de desarmar la referencia almacenada en $ row después del ciclo". debajo del ejemplo está en. – hakre

Cuestiones relacionadas