Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to dynamically set array keys in php

I have some logic that is being used to sort data but depending on the user input the data is grouped differently. Right now I have five different functions that contain the same logic but different groupings. Is there a way to combine these functions and dynamically set a value that will group properly. Within the function these assignments are happening

For example, sometimes I store the calculations simply by:

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

but other times need a more specific grouping:

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

As you can see sometimes it is stored in a multidiminesional array and other times not. I have been trying to use eval() but without success (not sure that is the correct approach). Storing the data in a temporary variable does not really save much because there are many nested loops and if statements so the array would have to be repeated in multiple places.

EDIT

I hope the following example explains my problem better. It is obviously a dumbed down version:

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

Now the same logic can be used but for storing it in different keys:

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

Is there a way to abstract out the keys in the $calc[] array so that I can have one function instead of having multiple functions with different array keys?

like image 239
Kramer Avatar asked Sep 13 '10 20:09

Kramer


People also ask

Which array has named keys PHP?

Associative arrays are arrays that use named keys that you assign to them.

What is the use of Array_keys in PHP?

The array_keys() is a built-in function in PHP and is used to return either all the keys of and array or the subset of the keys.

Is array key set PHP?

array is not set. This is also a predefined function in PHP which checks whether an index or a particular key exists in an array or not. It does not evaluate the value of the key for any null values. It returns false if it does not find the key in the array and true in all other possible cases.


2 Answers

You can use this if you want to get&set array values dynamically.

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

How it works:

Calling getVal($data,array('foo','bar','2017-08')) will return the equivalent of $data['foo']['bar']['2017-08'].

Calling setVal($data,array('foo','bar','2017-08'),'hello') will set value as if you called $data['foo']['bar']['2017-08'] = 'hello'. non-existent keys will be created automatically by php magic.

This can be useful if you want to build the structure of the array dynamically.

like image 62
Manuel Otto Avatar answered Sep 25 '22 04:09

Manuel Otto


Here's a function I wrote for setting deeply nested members on arrays or objects:

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

Using your example data:

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

Results in output like:

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

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

        )

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

        )

)

The second argument to dict_set() is a $path string in dot-notation. You can build this using dynamic keys with period delimiters between the parts. The function works with arrays and objects.

It can also append incremental members to deeply nested array by using [] as an element of the $path. For instance: parent.child.child.[]

like image 35
Jeff Standen Avatar answered Sep 21 '22 04:09

Jeff Standen