Скажем, у меня есть данные в древовидной структуре, реализованные в виде массива массивов произвольной глубины, что-то вроде
print_r($my_array);
Array
(
[id] => 123
[value] => Hello, World!
[child] => Array
(
[name] => Foo
[bar] => baz
)
[otherchild] => Array
(
[status] => fubar
[list] => Array
(
[one] => 1
[two] => 3
)
)
[sanity] => unchecked
)
Теперь, используя одну строку в качестве ключа, я хотел бы обратиться к узлу на произвольной глубине. Допустим, у меня есть ключ примерно так:
$key = 'otherchild|list|two';
Используя этот ключ, я хочу иметь возможность обратиться к значению, хранящемуся в
$my_array['otherchild']['list']['two']
Очевидно, что я могу разобрать (‘|’, $ key), чтобы получить массив ключей, и сдвиг значений из этого и использование их для адресации под-массивов позволяет легко получить искомое значение, что-то вроде
$value = $my_array;
$keys = explode('|', $key);
while ($k = array_shift($keys)) {
if (isset($value[$k])) {
$value = $value[$k];
} else {
// handle failure
}
} // Here, if all keys exist, $value holds value of addressed node
Но я застрял, пытаясь обновить значения общим способом, то есть без необходимости прибегать к чему-то вроде
$keys = explode('|', $key);
if (count($keys) == 1) {
$my_array[$keys[0]] = $new_value;
} else if (count($keys) == 2) {
$my_array[$keys[0]][$keys[1]] = $new_value;
} else if ...
Есть идеи?
function setAt(array & $a, $key, $value)
{
$keys = explode('|', $key);
// Start with the root node (the array itself)
$node = & $a;
// Walk the tree, create nodes as needed
foreach ($keys as $k) {
// Create node if it does not exist
if (! isset($node[$k])) {
$node[$k] = array();
}
// Walk to the node
$node = & $node[$k];
}
// Position found; store the value
$node = $value;
}// Test
$array = array();
// Add new values
setAt($array, 'some|key', 'value1');
setAt($array, 'some|otherkey', 'val2');
setAt($array, 'key3', 'value3');
print_r($array);
// Overwrite existing values
setAt($array, 'some|key', 'new-value');
print_r($array);
setAt($array, 'some', 'thing');
print_r($array);
Если вы ищете короткий ответ, вы также можете использовать Eval ().
$elem = "\$array['" . str_replace("|", "']['", $key) . "']";
$val = eval("return isset($elem) ? $elem : null;");