I needed a PHP function that would filter values from one array into a new one, while also removing those values from the original array. After looking through the docs, I didn't see any such function, so I wrote my own. While I don't expect it to run with any comparable efficiency as a native function, I am curious if there are any optimization steps I could be missing.
This code is written for PHP 8.1.X
/**
* Extract values from an array, and return the results
*
* @param array $array The array to filter
* @param callable|string $callback Function to filter the array with
*
* @return array A new array containing the filtered elements
*/
function array_excise(array &$array, callable|string $callback): array {
$results = [];
$arr_len = count($array);
for($i = 0; $i < $arr_len; $i++) {
if(is_callable($callback))
{
if($callback($array[$i]))
{
$results[] = $array[$i];
unset($array[$i]);
}
}
else if(is_string($callback))
{
if(call_user_func($callback, $array[$i]))
{
$results[] = $array[$i];
unset($array[$i]);
}
}
}
$array = array_values($array);
return $results;
}
Usage Example:
$people = [
[
"name" => "Billy Jean",
"filter" => false,
],
[
"name" => "Ronald Reagan",
"filter" => true,
],
[
"name" => "Bill Clinton",
"filter" => true,
],
[
"name" => "Michael Jackson",
"filter" => false,
],
[
"name" => "Johnny Cash",
"filter" => false,
],
];
$presidents = array_excise($people, function($p){ return $p["filter"]; });
print_r($people);
print_r($presidents);
/* output
Array
(
[0] => Array
(
[name] => Billy Jean
[filter] =>
)
[1] => Array
(
[name] => Michael Jackson
[filter] =>
)
[2] => Array
(
[name] => Johnny Cash
[filter] =>
)
)
Array
(
[0] => Array
(
[name] => Ronald Reagan
[filter] => 1
)
[1] => Array
(
[name] => Bill Clinton
[filter] => 1
)
)
*/