2010-09-13 12 views
6

Mam trochę logiki, która jest używana do sortowania danych, ale w zależności od danych wprowadzanych przez użytkownika dane są pogrupowane w inny sposób. Obecnie mam pięć różnych funkcji, które zawierają tę samą logikę, ale różne grupy. Czy istnieje sposób na połączenie tych funkcji i dynamiczne ustawienie wartości, która będzie należycie grupowana. Wewnątrz funkcji te zadania są dziejeJak dynamicznie ustawiać klucze tablicy w php

Na przykład, czasami przechowywać obliczeń po prostu:

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

ale czasami potrzebujemy bardziej konkretne ugrupowania:

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

Jak widać czasami jest przechowywany w tablicy wielowymiarowej, a innym razem nie. Próbowałem użyć eval(), ale bez powodzenia (nie jestem pewien, czy to właściwe podejście). Przechowywanie danych w zmiennej tymczasowej tak naprawdę nie oszczędza zbyt wiele, ponieważ istnieje wiele zagnieżdżonych pętli i instrukcji, więc tablica musiałaby być powtarzana w wielu miejscach.

EDIT

Mam nadzieję, że poniższy przykład wyjaśnia mój problem lepiej. To jest oczywiście dumbed dół wersja:

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

Teraz ta sama logika może być używany, ale do przechowywania go w różnych kluczy:

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; 
    } 
} 

Czy istnieje sposób do abstrakcyjne poza kluczami w $ calc [] tablica tak, że mogę mieć jedną funkcję, zamiast mieć wiele funkcji z różnymi kluczami tablicy?

+6

Czy można lepiej zarządzać przy użyciu obiektów? –

+2

Naprawdę nie rozumiem problemu. Czy próbujesz przesłać zapytania o te struktury danych w jednolity sposób? – erisco

+1

Zrobiłem edycję, aby pomóc wyjaśnić. Mam nadzieję, że to pomoże. – Kramer

Odpowiedz

0

Czy nie byłoby łatwiej wykonać następujące czynności

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

można też używać obiektów

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

ale radziłbym Ci zbudować swoją strukturę w macierzy, a następnie zrobić!

$calcs = (object)$calcs_array; 

lub możesz zapętlić pierwszą tablicę do nowej tablicy!

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

Daj temu i zobacz, jak wychodzi struktura tablicy.

+0

Nie jestem pewien, czy pytanie było jasne. Dokonałem pewnych zmian, aby spróbować wyjaśnić. – Kramer

0

Spróbuj użyć obudowy przełącznika.

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

Zgadzam się z komentarzem do OP przez @Jake N, że być może przy użyciu obiektów jest lepszym podejściem.Niemniej jednak, jeśli chcesz korzystać z tablic, można sprawdzić na istnienie kluczy warunkowe, tak jak poniżej:

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

Z drugiej strony, jeśli chcesz korzystać z obiektów można utworzyć typ MeterReading obiektu , a następnie dodać MeterReading instancji jako elementy tablicy do tablicy $calcs, tak:

// 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>'; 
} 

Oczywiście można wziąć to dalej, takie jak sprawdzanie istnienia kluczy tablicy w konstruktorze obiektu, dając właściwości obiektu resource domyślna wartość, jeśli nie została podana, i tak dalej, ale jest to początek do Podejście OO.

0

Możesz użyć tego, jeśli chcesz, aby ustawić wartości tablicowe & dynamicznie.

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; 
} 

Jak to działa:

Wywołanie getVal($data,array('foo','bar','2017-08')) zwróci równowartość $data['foo']['bar']['2017-08'].

Wywołanie setVal($data,array('foo','bar','2017-08'),'hello') ustawi wartość tak, jakby wywołać $data['foo']['bar']['2017-08'] = 'hello'. nieistniejące klucze zostaną utworzone automatycznie przez php magic.

Może to być przydatne, jeśli chcesz dynamicznie budować strukturę tablicy.

0

Oto funkcja Napisałem do ustawiania głęboko zagnieżdżonych członków na tablicach lub obiektów:

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; 
} 

Twoje przykładowe dane:

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

Wyniki produkcji jak:

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

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

     ) 

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

     ) 

) 

Drugi argument do dict_set() jest ciągiem $path w dot-notation. Można to zbudować za pomocą kluczy dynamicznych z ogranicznikami okresów między częściami. Funkcja działa z tablicami i obiektami.

Może również dołączać przyrostowe elementy do głęboko zagnieżdżonej tablicy, używając [] jako elementu $path. Na przykład: parent.child.child.[]

Powiązane problemy