Although my implementation using array_udiff()
was bad (it only works for a subset of cases), using array_udiff()
to filter elements is a bad idea anyway because of the underlying sorting algorithms applied to the arrays.
Nevertheless, I like the RFC's idea, highlighted by @mickmackusa, of being able to use certain array operations on enumeration arrays.
The implementation below using array_udiff()
with the spaceship operator and the enumeration name works now correctly, but is nevertheless very slow with large arrays.
array_udiff($all, $filtered, fn($item1, $item2) => $item1->name <=> $item2->name) ;
I performed performance tests with the following functions using a hundred-value enumeration class:
foreach
and in_array()
array_reduce()
and in_array()
array_filter()
and in_array()
array_walk()
and in_array()
array_udiff()
On my hardware with PHP 8.4, using the foreach
loop in conjunction with the in_array()
function gives the fastest results, while using the array_reduce()
and array_filter()
functions instead is about ~20% slower, the array_walk()
function is about ~30% slower, and using the array_udiff()
function is by far much slower, by over 380%.
array_reduce($all, function ($carry, $case) use ($filtered) {
if (!in_array($case, $filtered, true)) {
$carry[] = $case;
}
return $carry;
}, []);
array_filter($all, fn($case) => !in_array($case, $filtered, true));
$diff = [];
array_walk($all, function ($value) use ($filtered, &$diff) {
if (!in_array($value, $filtered, true)) {
$diff[] = $value;
}
}, $diff);