-1

is there a PHP function that would create a (deep) array key from an array ? It's quite difficult to explain, see that example:

function mysterious_function($input,$keys,$value){
    //...
    return $output;
}

$array = array(
    'hello'=>array(
        'im'=>'okay'
    )
);

$array = mysterious_function($array,array('hello','youre'),'beautiful');
$array = mysterious_function($array,array('ilove','the'),'haircut');

//would output

array(
    'hello'=>array(
        'im' =>         'ok',
        'youre' =>      'beautiful',
    ),
    'ilove'=>array(
        'the' =>        'haircut'
    )
);
mickmackusa
  • 37,596
  • 11
  • 75
  • 105
gordie
  • 1,251
  • 2
  • 15
  • 29
  • it's for a feedback function that would output a JSON. I would like to be able to "format" the response with keys, they might have any deepness. – gordie Jul 24 '19 at 22:05
  • 2
    I think this should probably answer your question: https://stackoverflow.com/questions/27929875/how-to-access-and-manipulate-multi-dimensional-array-by-key-names-path/27930028 – Don't Panic Jul 24 '19 at 22:12
  • 1
    Please show a more challenging depth demonstration, your posted sample is too shallow to express your potential complexity. Are all of keys unique in the whole array? Are the keys down each descendant branch unique? If a key already exists, do you want to overwrite the value, or create a new indexed subarray so that the old data and the new data are retained? – mickmackusa Jul 24 '19 at 22:22
  • 1
    Recursion: see Recursion. – Sammitch Jul 24 '19 at 23:52

2 Answers2

0

I don't know if this could help you:

function mysterious_function($array,$keys,$value){
    
    $stack = "";
    foreach($keys as $k){
        $stack .= "['{$k}']";
    }
    eval("\$array{$stack} = \$value;");
    
    return $array;
    
}

Yes, it's brutal :-D

Demo: http://sandbox.onlinephpfunctions.com/code/3091e831982df4f4fafca6f7e1fd05c31cdee526

Edit:

Often eval() is evil. Often there is another way to do this; by the way I hope this could help you.

Community
  • 1
  • 1
icy
  • 1,438
  • 3
  • 15
  • 34
  • 1
    Pretty cool! But note that: "The [eval()](https://www.php.net/manual/en/function.eval.php) language construct is *very dangerous* because it allows execution of arbitrary PHP code. *Its use thus is discouraged*. If you have carefully verified that there is no other option than to use this construct, pay special attention *not to pass any user provided data into it* without properly validating it beforehand." Maybe there's an alternative? – showdev Jul 24 '19 at 22:21
  • I'm agree with you @showdev. Usually `eval()` is evil, but sometimes it could be useful. I do not know if this can actually help someone but I did not understand downvote. – icy Jul 24 '19 at 22:28
  • Downvote's not mine. But it's an interesting concept and I still think it might be worth finding an alternative to `eval()`, if possible. – showdev Jul 24 '19 at 22:30
  • The downvote is from me (I didn't have time to comment because I had to get off the train) for two reasons: 1. `eval()` should be Plan Z and only entertained after Plan A through Plan Y have been proven to fail. 2. Your demonstration works because the posted sample data is very forgiving. The truth is the question is underdeveloped and doesn't sufficiently expose the variability/complexity of the data structures in the application. I feel your snippet is more likely to fail than success "in the wild". For these reasons, I don't recommend devs to use this technique and voted accordingly. – mickmackusa Jul 24 '19 at 22:49
0
<?
// I think I understand your use-case: Say I receive data expressed in a format like "Earth Science : Geology : Late Permian : Ice Depth = 30 feet"
// Parsing off the fact at the right is easy; setting the facts into a hierarchy is harder

function appendDeepArrayItem(&$array, $keys, $value)
{
    if (!is_array($array)) {
        die("First argument must be an array");
    }
    if (!is_array($keys)) {
        die("Second argument must be an array");
    }

    $currentKey = array_shift($keys);

    // If we've worked our way to the last key...
    if (count($keys) == 0) {
        if (is_array($value)) {
            foreach($value as $k=>$v) {
                $array[$currentKey][$k] = $v;
            }
        } else {
            $array[$currentKey][] = $value;
        }

    // Recurses Foiled Again! gotta keep digging... 
    } else {
        if (!array_key_exists($currentKey, $array)) {
            $array[$currentKey] = [];
        }
        appendDeepArrayItem($array[$currentKey], $keys, $value);
    }
}


$tree = [];

$parentKeys = explode(':', preg_replace('/\W:\W/', ':', "Earth Science : Geology : Late Permian"));
appendDeepArrayItem($tree, $parentKeys, ['Ice-depth in my back yard'=>'20 feet']);
appendDeepArrayItem($tree, $parentKeys, ['Unladen sparrow speed'=>'97 feet/second']);

$parentKeys = explode(':', preg_replace('/\W:\W/', ':', "Earth Science : Geology : Late Permian : About Frogs"));
appendDeepArrayItem($tree, $parentKeys, ['Croak loudness'=>'Very very loud']);

$parentKeys = explode(':', preg_replace('/\W:\W/', ':', "Earth Science : Geology : Paleoarchean"));
appendDeepArrayItem($tree, $parentKeys, ['Ice-depth in my back yard'=>'300 feet']);

echo "<pre>" . json_encode($tree, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);

// Produces the following output:    
{
    "Earth Science": {
        "Geology": {
            "Late Permian": {
                "Ice-depth in my back yard": "20 feet",
                "Unladen sparrow speed": "97 feet/second",
                "About Frogs": {
                    "Croak loudness": "Very very loud"
                }
            },
            "Paleoarchean": {
                "Ice-depth in my back yard": "300 feet"
            }
        }
    }
}
mcstafford
  • 81
  • 1
  • 2