Hi internals,
Currently, array_filter will always return the original keys.
This often requires an additional wrapping call of array_values(array_filter(...)) to reindex the keys and return a list.
(or applications may not realize there will be gaps in the keys until it causes a bug or unexpected JSON encoding, etc.)
PHP is also more memory/time efficient at creating packed arrays than it is at creating associative arrays.
What are your thoughts on adding ARRAY_FILTER_REINDEX
, to ignore the original int/string keys and replace them with 0, 1, 2, ...
php > echo json_encode(array_filter([5,6,7,8], fn($value) => $value % 2 > 0));
{"0":5,"2":7}
// proposed flag
php > echo json_encode(array_filter([5,6,7,8], fn($value) => $value % 2 > 0, ARRAY_FILTER_REINDEX));
[5,7]
https://www.php.net/array_filter already has the int $mode = 0
which accepts the bit flags ARRAY_FILTER_USE_KEY
and ARRAY_FILTER_USE_BOTH
These could be then be combined with the proposed bit flag ARRAY_FILTER_REINDEX
, e.g. to filter an array based on both the array keys and values, and return a list without gaps.
(and if $callback is null, this would return a list containing only the truthy values)
Thoughts?
Thanks,
Tyson
Hi internals,
Currently, array_filter will always return the original keys.
This often requires an additional wrapping call of
array_values(array_filter(...)) to reindex the keys and return a list.
(or applications may not realize there will be gaps in the keys until
it causes a bug or unexpected JSON encoding, etc.)PHP is also more memory/time efficient at creating packed arrays than
it is at creating associative arrays.What are your thoughts on adding
ARRAY_FILTER_REINDEX
, to ignore the
original int/string keys and replace them with0, 1, 2, ...
php > echo json_encode(array_filter([5,6,7,8], fn($value) => $value % 2 > 0)); {"0":5,"2":7} // proposed flag php > echo json_encode(array_filter([5,6,7,8], fn($value) => $value % 2 > 0, ARRAY_FILTER_REINDEX)); [5,7]
https://www.php.net/array_filter already has the
int $mode = 0
which
accepts the bit flagsARRAY_FILTER_USE_KEY
andARRAY_FILTER_USE_BOTH
These could be then be combined with the proposed bit flag
ARRAY_FILTER_REINDEX
, e.g. to filter an array based on both the array
keys and values, and return a list without gaps.
(and if $callback is null, this would return a list containing only the
truthy values)Thoughts?
Thanks,
Tyson
In cases where I do want it reindexed, the existing array_values()
is fine in most cases. Creating small, purpose-built tools that are easily composed is generally the right strategy. The only time I could see a flag being a better alternative is when the memory difference would be huge. Do we have a sense for how much of a memory difference we'd be looking at by combining it into a single operation?
(There's also the grossness of nesting functions inside each other, but the answer to that is pipes, not more flags.)
--Larry Garfield
On Sun, 19 Sept 2021 at 14:12, tyson andre tysonandre775@hotmail.com
wrote:
What are your thoughts on adding
ARRAY_FILTER_REINDEX
, to ignore the
original int/string keys and replace them with0, 1, 2, ...
If it's measurably faster/more memory efficient than
array_values(array_filter(...)) across a range of array sizes, I'm strongly
in favour as I write this a lot.
Peter
Hi, I myself faced such bugs because filter function preserves keys. From
my experience it is not that easy to locate bug like this. In my case I
rewrote solution in other way than it was originally written. Only later I
realized that root cause was array_filter
Hi internals,
Currently, array_filter will always return the original keys.
This often requires an additional wrapping call of
array_values(array_filter(...)) to reindex the keys and return a list.
(or applications may not realize there will be gaps in the keys until it
causes a bug or unexpected JSON encoding, etc.)PHP is also more memory/time efficient at creating packed arrays than it
is at creating associative arrays.What are your thoughts on adding
ARRAY_FILTER_REINDEX
, to ignore the
original int/string keys and replace them with0, 1, 2, ...
php > echo json_encode(array_filter([5,6,7,8], fn($value) => $value % 2 > 0)); {"0":5,"2":7} // proposed flag php > echo json_encode(array_filter([5,6,7,8], fn($value) => $value % 2 > 0, ARRAY_FILTER_REINDEX)); [5,7]
https://www.php.net/array_filter already has the
int $mode = 0
which
accepts the bit flagsARRAY_FILTER_USE_KEY
andARRAY_FILTER_USE_BOTH
These could be then be combined with the proposed bit flag
ARRAY_FILTER_REINDEX
, e.g. to filter an array based on both the array
keys and values, and return a list without gaps.
(and if $callback is null, this would return a list containing only the
truthy values)Thoughts?
Thanks,
TysonTo unsubscribe, visit: https://www.php.net/unsub.php
On Mon, Sep 20, 2021 at 12:02 PM Eugene Sidelnyk zsidelnik@gmail.com
wrote:
From my experience it is not that easy to locate bug like this.
Heyo, just a tip for you (and others in this thread), but if you use
vimeo/psalm
and declare a list<T>
for a type, then array_filter()
that are missing an array_values()
around it will be caught :)
/** @return list<mixed> */
function foo(array $input): array {
return array_filter($input);
}
Will produce:
INFO: MixedReturnTypeCoercion - 5:12 - The type 'array<array-key,
non-empty-mixed>' is more general than the declared return type
'list<mixed>' for foo
See https://psalm.dev/r/f9c51f72c2
Marco Pivetta
On Sun, Sep 19, 2021 at 3:11 PM tyson andre tysonandre775@hotmail.com
wrote:
Hi internals,
Currently, array_filter will always return the original keys.
This often requires an additional wrapping call of
array_values(array_filter(...)) to reindex the keys and return a list.
(or applications may not realize there will be gaps in the keys until it
causes a bug or unexpected JSON encoding, etc.)
Hi,
This "issue" is not limited to array_filter()
, there's also array_unique()
and even array_diff()
/array_intersect() whose variadic signature doesn't
allow to add a flag (I think?)...
PS: and array_column()
has the opposite issue...
--
Guilliam Xavier