1

I have this string: test1__test2__test3__test4__test5__test6=value

There could be any number of test-keys.

I want to write a function that can turn the string above into an array

$data[test1][test2][test3][test4][test5][test6] = "value";

Is this possible?

3
  • 2
    Seems a bit complicated, why do you need to do this for? Commented Jun 20, 2011 at 13:53
  • Is it always going to be 6 items or more/less? Commented Jun 20, 2011 at 14:37
  • @Salman: "There could be any number of test-keys." -- I guess 6 is an arbitrary example. Commented Jun 20, 2011 at 14:47

5 Answers 5

3
function special_explode($string) {
  $keyval = explode('=', $string);
  $keys = explode('__', $keyval[0]);
  $result = array();

  //$last is a reference to the latest inserted element                         
  $last =& $result;
  foreach($keys as $k) {
    $last[$k] = array();
    //Move $last                                                                
    $last =& $last[$k];
  }

  //Set value                                                                   
  $last = $keyval[1];
  return $result;
}

//Test code:
$string = 'test1__test2__test3__test4__test5__test6=value';
print_r(special_explode($string));
Sign up to request clarification or add additional context in comments.

Comments

3

Yes it is possible:

list($keys, $value) = explode('=', $str);
$keys = explode('__', $keys);

$t = &$data;
$last = array_pop($keys);

foreach($keys as $key) {
    if(!isset($t[$key]) || !is_array($t[$key])) {
        // will override non array values if present
        $t[$key] = array();
    }
    $t = &$t[$key];
}

$t[$last] = $value;

DEMO

Reference: list, explode, =&, is_array, array_pop

5 Comments

@Ferdinand: Thanks! That happens when you code too fast :D ;)
Furthermore, is_array($data[$key]) will issue warnings (or even errors?) if $key is not in $data. Did you mean isset()? ;)
@Ferdinand: You are right, it gives a notice. But no, I wanted to use is_array. Just have to add isset. Thanks again! :)
Thank you for the references.
if you look at the output of the demo more closely you'll notice test6 appears twice.
2
$data = array();

// Supposing you have multiple strings to analyse...
foreach ($strings as $string) {
    // Split at '=' to separate key and value parts.
    list($key, $value) = explode("=", $string);

    // Current storage destination is the root data array.
    $current =& $data;

    // Split by '__' and remove the last part
    $parts = explode("__", $key);
    $last_part = array_pop($parts);

    // Create nested arrays for each remaining part.
    foreach ($parts as $part)
    {
        if (!array_key_exists($part, $current) || !is_array($current[$part])) {
            $current[$part] = array();
        }
        $current =& $current[$part];
    }

    // $current is now the deepest array ($data['test1']['test2'][...]['test5']).
    // Assign the value to his array, using the last part ('test6') as key.
    $current[$last_part] = $value;
}

1 Comment

thanks for that. I needed to analyze a lot of strings and then compile one big array.
1
$str = ...;
eval( str_replace('__', '][', 
preg_replace('/^(.*)=(.*)$/', '\$data[$1]=\'$2\';', $str)) );

easier way, assuming the $str is trustable data

2 Comments

You should at least add quotes to the keys. Otherwise you will get warnings that you use undefined constants, and, if one of the keys happens to be a constant name, you will get into trouble. Maybe you should also emphasize the trustable aspect...
Agree with Ferinand. But otherwise nice solution. It's the first piece of code with eval I see, which I would've accepted in my own project 8) .
0

I suppose it is...

$string = "test1__test2__test3__test4__test5__test6=value";
$values = explode('=',$string);
$indexes = explode('__',$values[0]);
$data[$indexes[0]][$indexes[1]][$indexes[2]][$indexes[3]][$indexes[4]][$indexes[5]] = $values[1];

1 Comment

explode() can't handle regular expressions, so explode('_+') won't split on __.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.