2010-09-13 14 views
6

Tengo un poco de lógica que se utiliza para ordenar los datos, pero dependiendo de la entrada del usuario, los datos se agrupan de manera diferente. En este momento tengo cinco funciones diferentes que contienen la misma lógica pero diferentes agrupaciones. ¿Hay alguna forma de combinar estas funciones y establecer dinámicamente un valor que se agrupe correctamente? Dentro de la función de estas asignaciones están sucediendoCómo establecer dinámicamente claves de matriz en php

Por ejemplo, a veces almaceno los cálculos simplemente por:

$calcs[$meter['UnitType']['name']] = ... 

pero otras veces necesito una agrupación más específico:

$calcs[$meter['Resource']['name']][$meter['UnitType']['name']][date('Y-m',$start)] =... 

Como se puede ver en ocasiones se almacena en una matriz multidiminesional y otras veces no. He estado tratando de usar eval() pero sin éxito (no estoy seguro de que sea el enfoque correcto). Almacenar los datos en una variable temporal realmente no ahorra mucho porque hay muchos bucles anidados y sentencias if para que la matriz tenga que repetirse en varios lugares.

EDITAR

espero que el siguiente ejemplo explica mejor mi problema. Obviamente es un callados versión:

if(){ 
    $calcs[$meter['UnitType']['name']] = $data; 
} else { 
    while() { 
     $calcs[$meter['UnitType']['name']] = $data; 
    } 
} 

Ahora la misma lógica se puede utilizar, pero para su almacenamiento en diferentes claves:

if(){ 
    $calcs[$meter['Resource']['name']][$meter['UnitType']['name']][date('Y-m',$start)] = $data; 
} else { 
    while() { 
     $calcs[$meter['Resource']['name']][$meter['UnitType']['name']][date('Y-m',$start)] = $data; 
    } 
} 

¿Hay una manera de abstraer las teclas en el $ calc [] matriz para que pueda tener una función en lugar de tener múltiples funciones con diferentes teclas de matriz?

+6

¿Se podría gestionar mejor usando objetos? –

+2

Realmente no entiendo el problema. ¿Estás tratando de consultar estas estructuras de datos de manera uniforme? – erisco

+1

Hice una edición para ayudar a explicar. Espero que ayude. – Kramer

Respuesta

0

¿No sería más fácil hacer lo siguiente

$calcs = array(
    $meter['Resource']['name'] => array(
     $meter['UnitType']['name'] => 'Some Value', 
     $meter['UnitType']['name2'] => 'Some Value Again' 
    ), 
); 

o puede utilizar objetos

$calcs = new stdClass(); 
$calcs->{$meter['UnitType']['name']} = 'Some Value'; 

pero yo aconsejaría a construir su estructura de matrices y luego haces!

$calcs = (object)$calcs_array; 

o puede hacer un bucle de su primer conjunto en una nueva matriz!

$new = array(); 
$d = date('Y-m',$start); 
foreach($meter as $key => $value) 
{ 
    $new[$key]['name'][$d] = array(); 
} 

Dale esto y mira cómo sale la estructura de la matriz.

+0

No estoy seguro de que la pregunta sea clara. He hecho algunas ediciones para tratar de ayudar a explicar. – Kramer

0

Intente usar una caja de interruptores.

<?php 
$userinput = $calcs[$meter['UnitType']['name']] = $data;; 

switch ($userinput) { 
    case "useriput1": 
    while() { 
     $calcs[$meter['Resource']['name']][$meter['UnitType']['name']][date('Y-m',$start)] = $data; 
    } 
    break; 
    case "userinput2": 
    while() { 
     $calcs[$meter['Resource']['name']][$meter['UnitType']['name']][date('Y-m',$start)] = $data; 
    } 
    break; 

    ... 

    default: 
    while() { 
     $calcs[$meter['Resource']['name']][$meter['UnitType']['name']][date('Y-m',$start)] = $data; 
    } 
} 
?> 
0

Estoy de acuerdo con el comentario sobre el OP de @Jake N que tal vez el uso de objetos es un mejor enfoque.Sin embargo, si desea utilizar matrices, se puede comprobar la existencia de llaves en un condicional, así:

if(
    array_key_exists('Resource', $meter) 
) { 
    $calcs[$meter['Resource']['name']][$meter['UnitType']['name']][date('Y-m',$start)] = $data; 
} else { 
    $calcs[$meter['UnitType']['name']] = $data; 
} 

Por otro lado, si desea utilizar objetos, puede crear un tipo MeterReading objeto , y luego añadir MeterReading casos como elementos de la matriz de la matriz $calcs, así:

// Object defintion 
class MeterReading { 
    private $data; 
    private $resource; 
    private $startDate; 
    private $unitType; 

    public function __construct(Array $meter, $start, $data) { 
     $this->unitType = $meter['UnitType']['name']; 
     $this->resource = $meter['Resource']['name']; 
     $this->startDate = date('Y-m',$start); 
    } 

    public function data() { 
     return $this->data; 
    } 

    public function resource() { 
     return $this->resource; 
    } 

    public function startDate() { 
     return $this->startDate; 
    } 

    public function unitType() { 
     return $this->unitType; 
    } 
} 

// Example population 
$calcs[] = new MeterReading($meter, $start, $data); 

// Example usage 
foreach($calcs as $calc) { 
    if($calc->resource()) { 
     echo 'Resource: ' . $calc->resource() . '<br>'; 
    } 
    echo 'Unit Type: ' . $calc->unitType() . '<br>'; 
    echo 'Start Date: ' . $calc->startDate() . '<br>'; 
    echo 'Data: ' . $calc->data() . '<br>'; 
} 

Obviamente se puede ir más lejos, como la comprobación de la existencia de claves de matriz en el constructor de objetos, dando la propiedad del objeto resource una valor predeterminado si no se proporciona, y así sucesivamente, pero esto es un comienzo para un Enfoque OO.

0

Puede usar esto si desea obtener & establecer valores de matriz dinámicamente.

function getVal($data,$chain){ 
    $level = $data; 
    for($i=0;$i<count($chain);$i++){ 
     if(isset($level[$chain[$i]])) 
      $level = $level[$chain[$i]]; 
     else 
      return null; // key does not exist, return null 
    } 
    return $level; 
} 

function setVal(&$data,$chain,$value){ 
    $level = &$data; 
    for($i=0;$i<count($chain);$i++){ 
     $level = &$level[$chain[$i]]; // set reference (&) in order to change the value of the object 
    } 
    $level = $value; 
} 

Cómo funciona:

Calling getVal($data,array('foo','bar','2017-08')) devolverá el equivalente de $data['foo']['bar']['2017-08'].

Llamar setVal($data,array('foo','bar','2017-08'),'hello') establecerá el valor como si llamara $data['foo']['bar']['2017-08'] = 'hello'. las claves inexistentes se crearán automáticamente por php magic.

Esto puede ser útil si desea construir dinámicamente la estructura de la matriz.

0

Aquí es una función que escribí para el establecimiento de los miembros anidadas en arrays u objetos:

function dict_set($var, $path, $val) { 
    if(empty($var)) 
     $var = is_array($var) ? array() : new stdClass(); 

    $parts = explode('.', $path); 
    $ptr =& $var; 

    if(is_array($parts)) 
    foreach($parts as $part) { 
     if('[]' == $part) { 
      if(is_array($ptr)) 
       $ptr =& $ptr[]; 

     } elseif(is_array($ptr)) { 
      if(!isset($ptr[$part])) 
       $ptr[$part] = array(); 

      $ptr =& $ptr[$part]; 

     } elseif(is_object($ptr)) { 
      if(!isset($ptr->$part)) 
       $ptr->$part = array(); 

      $ptr =& $ptr->$part; 
     } 
    } 

    $ptr = $val; 

    return $var; 
} 

El uso de sus datos de ejemplo:

$array = []; 

$array = dict_set($array, 'resource1.unit1.2017-10', 'value1'); 
$array = dict_set($array, 'resource1.unit2.2017-11', 'value2'); 
$array = dict_set($array, 'resource2.unit1.2017-10', 'value3'); 

print_r($array); 

Resultados en una salida como:

Array 
(
    [resource1] => Array 
     (
      [unit1] => Array 
       (
        [2017-10] => value1 
       ) 

      [unit2] => Array 
       (
        [2017-11] => value2 
       ) 

     ) 

    [resource2] => Array 
     (
      [unit1] => Array 
       (
        [2017-10] => value3 
       ) 

     ) 

) 

El segundo argumento para dict_set() es una cadena $path en notación de puntos. Puede construir esto usando claves dinámicas con delimitadores de período entre las partes. La función funciona con matrices y objetos.

También puede agregar miembros incrementales a una matriz anidada profundamente usando [] como un elemento de $path. Por ejemplo: parent.child.child.[]

Cuestiones relacionadas