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?
Felix Kling
820k181 gold badges1.1k silver badges1.2k bronze badges
asked Jun 20, 2011 at 13:51
Rasmus Styrk
1,3462 gold badges20 silver badges36 bronze badges
-
2Seems a bit complicated, why do you need to do this for?Tomgrohl– Tomgrohl2011年06月20日 13:53:27 +00:00Commented Jun 20, 2011 at 13:53
-
Is it always going to be 6 items or more/less?Salman Arshad– Salman Arshad2011年06月20日 14:37:58 +00:00Commented Jun 20, 2011 at 14:37
-
@Salman: "There could be any number of test-keys." -- I guess 6 is an arbitrary example.Ferdinand Beyer– Ferdinand Beyer2011年06月20日 14:47:33 +00:00Commented Jun 20, 2011 at 14:47
5 Answers 5
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));
answered Jun 20, 2011 at 13:59
Emil Vikström
92.3k17 gold badges144 silver badges178 bronze badges
Sign up to request clarification or add additional context in comments.
Comments
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;
answered Jun 20, 2011 at 13:58
Felix Kling
820k181 gold badges1.1k silver badges1.2k bronze badges
5 Comments
Felix Kling
@Ferdinand: Thanks! That happens when you code too fast :D ;)
Ferdinand Beyer
Furthermore,
is_array($data[$key]) will issue warnings (or even errors?) if $key is not in $data. Did you mean isset()? ;)Felix Kling
@Ferdinand: You are right, it gives a notice. But no, I wanted to use
is_array. Just have to add isset. Thanks again! :)Rasmus Styrk
Thank you for the references.
Salman Arshad
if you look at the output of the demo more closely you'll notice
test6 appears twice.$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;
}
answered Jun 20, 2011 at 13:58
Ferdinand Beyer
67.6k18 gold badges161 silver badges147 bronze badges
1 Comment
Rasmus Styrk
thanks for that. I needed to analyze a lot of strings and then compile one big array.
$str = ...;
eval( str_replace('__', '][',
preg_replace('/^(.*)=(.*)$/', '\$data[1ドル]=\'2ドル\';', $str)) );
easier way, assuming the $str is trustable data
answered Jun 20, 2011 at 14:00
ajreal
47.4k11 gold badges98 silver badges119 bronze badges
2 Comments
Ferdinand Beyer
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...
Slava
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) .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];
answered Jun 20, 2011 at 13:56
SteeveDroz
6,1646 gold badges36 silver badges69 bronze badges
1 Comment
Ferdinand Beyer
explode() can't handle regular expressions, so explode('_+') won't split on __.lang-php