I am trying to create a function to remove keys from a dynamic multidimensional array, i need to give:
removeByIndex(['hello', 'my', 'world']);
And then the function needs to do this:
unset($array['hello']['my']['world']);
The number of indexes are dynamic, example:
removeByIndex(['hello', 'my']); // Do: unset($array['hello']['my']);
removeByIndex(['hello']); // Do: unset($array['hello']);
I tried to use some foreach
loops, but i didn't find a solution yet.
Any help will be welcome.
No need for eval()
with a little bit of referencing.
/**
* Remove index from multi-dimensional array.
*
* @param array $array
* The array to remove the index from.
* @param array $indices
* Indexed array containing the indices chain up to the index that should be
* removed.
* @return
* The array with the index removed.
* @throws \InvalidArgumentException
* If the index does not exist within the array.
*/
function removeByIndex(array $array, array $indices) {
// Create a reference to the original array.
$a =& $array;
// Count all passed indices, remove one because arrays are zero based.
$c = count($indices) - 1;
// Iterate over all passed indices.
for ($i = 0; $i <= $c; ++$i) {
// Make sure the index to go down for deletion actually exists.
if (array_key_exists($indices[$i], $a)) {
// This is the target if we reached the last index that was passed.
if ($i === $c) {
unset($a[$indices[$i]]);
}
// Make sure we have an array to go further down.
elseif (is_array($a[$indices[$i]])) {
$a =& $a[$indices[$i]];
}
// Index does not exist since there is no array to go down any further.
else {
throw new \InvalidArgumentException("{$indices[$i]} does not exist.");
}
}
// Index does not exist, error.
else {
throw new \InvalidArgumentException("{$indices[$i]} does not exist.");
}
}
return $array;
}
print_r(removeByIndex(
[ "test1" => [ "test2" => [ "test3" => "test" ] ], "test4" => "test" ],
[ "test1", "test2", "test3" ]
));
Since I mentioned it in the comments, one could (micro-)optimize the function, but I advice against it, since it is less readable and might confuse some programmers.
<?php
function removeByIndex(array $array, array $indices) {
$a =& $array;
$c = count($indices) - 1;
$i = 0;
do {
if (array_key_exists($indices[$i], $a)) {
if ($i === $c) {
unset($a[$indices[$i]]);
return $array;
}
elseif (is_array($a[$indices[$i]])) {
$a =& $a[$indices[$i]];
}
else break;
}
else break;
}
while (++$i);
throw new \InvalidArgumentException("{$indices[$i]} does not exist.");
}
Based on the briliant @Fleshgrinder answer, i am using this final version:
function removeByIndex($vars, $indexes) {
if ( ! is_array($indexes)) {
throw new \Exception('Array expected');
}
$array = & $vars;
$qtd_indexes = count($indexes);
for ($i = 0; $i < $qtd_indexes; $i++) {
if ( ! array_key_exists($indexes[$i], $array)) {
throw new \Exception($indexes[$i] . " doesn't exist");
}
// Check if it is the target entry
if ($i === $qtd_indexes - 1) {
unset($array[$indexes[$i]]);
} elseif (is_array($array[$indexes[$i]])) { // Check if exists one more level
$array = & $array[$indexes[$i]];
} else {
// If it isn't the target and it isn't an array, throw exception
throw new \Exception("Content of '" . $indexes[$i] . "' isn't an array");
}
}
return $vars;
}
I was researched for a couple of hours for this solution, nowhere found an optimal solution. so, i wrote it by myself
function allow_keys($arr, $keys)
{
$saved = [];
foreach ($keys as $key => $value) {
if (is_int($key) || is_int($value)) {
$keysKey = $value;
} else {
$keysKey = $key;
}
if (isset($arr[$keysKey])) {
$saved[$keysKey] = $arr[$keysKey];
if (is_array($value)) {
$saved[$keysKey] = allow_keys($saved[$keysKey], $keys[$keysKey]);
}
}
}
return $saved;
}
use: example
$array = [
'key1' => 'kw',
'loaa'=> ['looo'],
'k' => [
'prope' => [
'prop' => ['proo', 'prot', 'loolooo', 'de'],
'prop2' => ['hun' => 'lu'],
],
'prop1' => [
],
],
];
call: example
allow_keys($array, ['key1', 'k' => ['prope' => ['prop' => [0, 1], 'prop2']]])
output:
Array ( [key1] => kw [k] => Array ( [prope] => Array ( [prop] => Array ( [0] => proo [1] => prot ) [prop2] => Array ( [hun] => lu ) ) ) )
so you get only needed keys from the multidimensional array. it is not limited only for "multidimensional", you can use it by passing an array like
['key1', 'loaa']
output you get:
Array ( [key1] => kw [loaa] => Array ( [0] => looo ) )
i'm writing it here for reason that this topic is one of the first when you type on google
recursive remove keys multidimensional php
hope someone helps this one, as i searched a lot, and nothing found. cheers!