Reputation: 1953
Imagine you have a deep array like this:
<?php
$array = ['hello' => ['deep' => 'treasure']];
Then you had an array of the keys to access the string 'treasure'
['hello', 'deep'];
How do you delete the string treasure if you did not know the depth of the array till run time
Edit:
My apologises I've definitely not provided enough information for what I'm looking to achieve
Here is some code I've come up with which does what I need but uses unsafe eval (keep in mind the target destination could be an array so array_walk_recursive won't work)
function iterator_keys($iterator, $outer_data) {
$keys = array();
for ($i = 0; $i < $iterator->getDepth() + 1; $i++) {
$sub_iterator = $iterator->getSubIterator($i);
$keys[$i] = ($i == 0 && is_object($outer_data)
|| $i > 0 && is_object($last_iterator->current())) ?
'->{"' . $sub_iterator->key() . '"}' :
'["' . $sub_iterator->key() . '"]';
$last_iterator = $sub_iterator;
}
return $keys;
}
function recursive_filter($data, callable $selector_function, $iterator = NULL) {
$iterator = $iterator ?? new RecursiveIteratorIterator(
new RecursiveArrayIterator($data),
RecursiveIteratorIterator::CHILD_FIRST
);
foreach ($iterator as $key => $value) {
if ($selector_function($value, $key, $iterator)) {
eval('unset($data' . implode('', iterator_keys($iterator, $data)) . ');');
}
}
return $data;
}
The intention is to have a deep data structure a function that evalutes each node and if it matches a condition then remove it from the data structure in place, if this can be done without eval that would be amazing but so far I think PHP can't programmatically delete something that is more than one level deep
Upvotes: 1
Views: 263
Reputation: 78994
This will set the target array element to null
. Optionally you could use ''
:
$array = ['hello' => ['deep' => 'treasure']];
$path = ['hello', 'deep'];
$temp = &$array;
foreach($path as $key) {
$temp =& $temp[$key];
}
$temp = null;
print_r($array);
Yields:
Array
(
[hello] => Array
(
[deep] =>
)
)
Upvotes: 0
Reputation: 751
Well you can try this really quick and dirty way that uses eval to achieve your goal:
$array = ['hello' => ['deep' => 'treasure']];
$keys = ['hello', 'deep'];
$expression = 'unset($array[\'' . implode('\'][\'', $keys) . '\']);';
eval($expression);
But maybe you can tell us more about your development and we can help you reorganize it somehow to avoid this problem at all.
Upvotes: 0
Reputation: 1571
Hello I think what you want is somethings like this
<?php
$array = ['hello' => ['deep' => ['deep1' => 'treasure']]];
$keys = ["hello", "deep", "deep1"];
function remove_recursive(&$array, $keys, $level = 0)
{
if ($level >= count($keys)) {
return $array;
}
if (isset($array[$keys[$level]]) && $level == count($keys) - 1) {
unset($array[$keys[$level]]);
} elseif (isset($array[$keys[$level]])) {
$array[$keys[$level]] = remove_recursive($array[$keys[$level]], $keys, $level + 1);
}
return $array;
}
var_dump(remove_recursive($array, $keys));
Upvotes: 1