I have a class which stores values with a multi-level associative array:
I need to add a way to access and modify nested values. Here is a working solution for my problem, but it is rather slow. Is there a better way of doing this?
Note: The use of get / set functions is not mandatory, but there needs to be an efficient way to define a default value.
class Demo {
protected $_values = array();
function __construct(array $values) {
$this->_values = $values;
}
public function get($name, $default = null) {
$token = strtok($name, '.#');
$node = $this->_values;
while ($token !== false) {
if (!isset($node[$token]))
return $default;
$node = $node[$token];
$token = strtok('.#');
}
return $node;
}
public function set($name, $value) {
$next_token = strtok($name, '.#');
$node = &$this->_values;
while ($next_token !== false) {
$token = $next_token;
$next_token = strtok('.#');
if ($next_token === false) {
$node[ $token ] = $value;
break;
}
else if (!isset($node[ $token ]))
$node[ $token ] = array();
$node = &$node[ $token ];
}
unset($node);
}
}
Which would be used as follows:
$test = new Demo(array(
'simple' => 27,
'general' => array(
0 => array(
'something' => 'Hello World!',
'message' => 'Another message',
'special' => array(
'number' => 27
)
),
1 => array(
'something' => 'Hello World! #2',
'message' => 'Another message #2'
),
)
));
$simple = $test->get('simple'); // === 27
$general_0_something = $test->get('general#0.something'); // === 'Hello World!'
$general_0_special_number = $test->get('general#0.special.number'); === 27
Note: 'general.0.something' is the same as 'general#0.something', the alternative punctuation is for the purpose of clarity.
Zend_Dom_Querycomponent of Zend Framework. You might consider having a look at it: framework.zend.com/manual/en/zend.dom.query.htmlpreg_splitin stead ofstrtok, but it was twice as slow. So I think your solution is pretty fast as it is. I'd be surprised to see a faster solution.