Dear PHP Internals,
I would like to propose new functions to search in arrays: array_find() and
array_find_key().
array_find(): This function would allow developers to find the first
element in
an array that satisfies a specific condition. The condition would be
defined by
a callback function. The functionality would be similar to the existing
array_filter()
function but would instead return the first element that
matches
the callback condition, rather than all matching elements.
This function can be used in a way simliar to in_array with added
functionality
of custom check.
array_find_key(): This function would return the key of the first
element in an
array that matches a given condition, defined by a callback function. This
function can be used in a way simliar to array_search with added
functionality
of custom check.
Both functions stop processing after first match is found, so any side
effects
of the callbacks should be avoided.
Here are the proposed function definitions:
/**
* @param callable(mixed):bool $callback
*/
function array_find(callable $callback, array $array)
{
foreach ($array as $row) {
if (call_user_func($callback, $row) === true) {
return $row;
}
}
return null;
}
/**
* @param callable(mixed):bool $callback
* @return null|int|string
*/
function array_find_key(callable $callback, array $array)
{
foreach($array as $key => $row) {
if (call_user_func($callback, $row) === true) {
return $key;
}
}
return null;
}
Both functions are easy to implement in PHP (and probably as easy to
implement
in C), but IMHO could be nice addition to set of array related functions
in PHP.
If the response to this e-mail will be positive, I will prepare RFC.
We should also discuss order of arguments as the functions are similar
to both
array_search/in_array with condition-array and array_filter with
array-condition, but as you can see above I am leaning towards
condition-array.
Looking forward to hearing your thoughts.
Best regards,
Janusz
Dear PHP Internals,
I would like to propose new functions to search in arrays: array_find() and
array_find_key().array_find(): This function would allow developers to find the first
element in
an array that satisfies a specific condition. The condition would be
defined by
a callback function. The functionality would be similar to the existing
array_filter()
function but would instead return the first element that
matches
the callback condition, rather than all matching elements.
This function can be used in a way simliar to in_array with added
functionality
of custom check.array_find_key(): This function would return the key of the first
element in an
array that matches a given condition, defined by a callback function. This
function can be used in a way simliar to array_search with added
functionality
of custom check.Both functions stop processing after first match is found, so any side
effects
of the callbacks should be avoided.Here are the proposed function definitions:
/**
* @param callable(mixed):bool $callback
*/
function array_find(callable $callback, array $array)
{
foreach ($array as $row) {
if (call_user_func($callback, $row) === true) {
return $row;
}
}
return null;
}/**
* @param callable(mixed):bool $callback
* @return null|int|string
*/
function array_find_key(callable $callback, array $array)
{
foreach($array as $key => $row) {
if (call_user_func($callback, $row) === true) {
return $key;
}
}
return null;
}Both functions are easy to implement in PHP (and probably as easy to
implement
in C), but IMHO could be nice addition to set of array related functions
in PHP.If the response to this e-mail will be positive, I will prepare RFC.
We should also discuss order of arguments as the functions are similar
to both
array_search/in_array with condition-array and array_filter with
array-condition, but as you can see above I am leaning towards
condition-array.Looking forward to hearing your thoughts.
Best regards,
Janusz
As with the array_group thread:
What is the argument to put these functions in hard to update C, rather than PHP that is easy to download with Composer? "could be a nice addition" is not a compelling argument. Is it substantially faster? It is truly universally used? Does it correct some security concern?
Those are the questions that stdlib additions need to answer.
--Larry Garfield
Hi
As with the array_group thread:
What is the argument to put these functions in hard to update C, rather than PHP that is easy to download with Composer? "could be a nice addition" is not a compelling argument. Is it substantially faster? It is truly universally used? Does it correct some security concern?
I am not sure if "hard to update" is a argument that applies here: There
is only one reasonable implementation of array_find and thus once the
function is written it is exceedingly unlikely to need any updates. When
was the last time array_filter
, which is likely the most similar
existing function, needed an update?
From the list you've given, "universally used" appears to be the most
fitting description. A programming language needs a reasonable standard
library and array_find()
[1] is something that should pop up
reasonably often in "functional array processing". It's available in
various languages [2].
My only concern is that this either is another function that either
instead of working on any iterable, works on arrays and arrays only - or
a function that is inconsistent with the rest of the array_* functions.
See also the discussion here: https://externals.io/message/118896#118896
Best regards
Tim Düsterhus
[1] As well as array_any() and array_all().
[2]
JS:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find
Rust: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.find
Haskell:
https://hackage.haskell.org/package/base-4.18.0.0/docs/Data-List.html#v:find
C++: https://en.cppreference.com/w/cpp/algorithm/find
Hey,
Native implementation of the function array_find would decrease number of
lines needed to perform basic loops over the arrays from 4-6 lines to just
- And I recollect a few times when the argument of reducing lines of code
needed to type was a valid reason of implementing the change.
Moreover, only this function would allow to achieve the same result as
proposed functions any()/all() by Tyson Andre 3 years ago. I still cannot
understand the context why the rejection reasons as "Too small in
scope/Object to the choice of namespace/Prefer the global namespace"
prevented PHP to have something which is a basically standard in other
languages.
https://wiki.php.net/rfc/any_all_on_iterable
Kind regards,
Jorg
array_find(): This function would allow developers to find the first element in
an array that satisfies a specific condition. The condition would be defined by a callback function.
This would actually be an alternative to a simple foreach() with an if() and a break. As your example implementation makes clear.
array_find() and array_find_key() would still do the same internally, but add a function call adding the overhead of pushing parameters to stack, switching the scope, passing return value back switch scope and pop from the callstack again. If parameters or return value are typed this adds even more overhead.
I don't think there is any optimisation possible when this is done in C.
To the proposer it probably feels that this is an array function currently missing, but instead it's probably better not to have array_find() because people might actually use it for larger datasets.
Although I acknowledge that it will reduce the number of lines of PHP code it doesn't actually reduce the mental capacity to read and maintain code. I find the simple elemental building blocks of loops, conditionals and expressions easier and more expressive. In my experience this is especially so for less experienced developers.
Then there is a problem of naming. array_search()
and array_find(). To a new developer, how would they know which is which?
Also there is the missing array_find_value_and_key() method. Because why should we be limited to either matching the key OR the value?
Greetings, Casper
sounds like array_find could be implemented by just adding a new flag
for array_filter's $mode:
ARRAY_FILTER_STOP_ON_FIRST_MATCH
or some such?
array_find(): This function would allow developers to find the first element in
an array that satisfies a specific condition. The condition would be defined by a callback function.This would actually be an alternative to a simple foreach() with an if() and a break. As your example implementation makes clear.
array_find() and array_find_key() would still do the same internally, but add a function call adding the overhead of pushing parameters to stack, switching the scope, passing return value back switch scope and pop from the callstack again. If parameters or return value are typed this adds even more overhead.
I don't think there is any optimisation possible when this is done in C.
To the proposer it probably feels that this is an array function currently missing, but instead it's probably better not to have array_find() because people might actually use it for larger datasets.
Although I acknowledge that it will reduce the number of lines of PHP code it doesn't actually reduce the mental capacity to read and maintain code. I find the simple elemental building blocks of loops, conditionals and expressions easier and more expressive. In my experience this is especially so for less experienced developers.
Then there is a problem of naming.
array_search()
and array_find(). To a new developer, how would they know which is which?Also there is the missing array_find_value_and_key() method. Because why should we be limited to either matching the key OR the value?
Greetings, Casper
W dniu 2.06.2023 o 03:24, Hans Henrik Bergan pisze:
sounds like array_find could be implemented by just adding a new flag
for array_filter's $mode:
ARRAY_FILTER_STOP_ON_FIRST_MATCH
or some such?
array_filter is guaranteed to always return an array and we should not
change it.
Flags are used just to decide what should be sent to a callback.
In my other e-mail I have just proposed adding similiar flags to
array_find function as you have it now in array_filter, so it can be
used to search by keys and/or values.
Best regards,
Janusz
W dniu 2.06.2023 o 02:14, Casper Langemeijer pisze:
array_find(): This function would allow developers to find the first element in
an array that satisfies a specific condition. The condition would be defined by a callback function.
This would actually be an alternative to a simple foreach() with an if() and a break. As your example implementation makes clear.array_find() and array_find_key() would still do the same internally, but add a function call adding the overhead of pushing parameters to stack, switching the scope, passing return value back switch scope and pop from the callstack again. If parameters or return value are typed this adds even more overhead.
I don't think there is any optimisation possible when this is done in C.
To the proposer it probably feels that this is an array function currently missing, but instead it's probably better not to have array_find() because people might actually use it for larger datasets.
Although I acknowledge that it will reduce the number of lines of PHP code it doesn't actually reduce the mental capacity to read and maintain code. I find the simple elemental building blocks of loops, conditionals and expressions easier and more expressive. In my experience this is especially so for less experienced developers.
Then there is a problem of naming.
array_search()
and array_find(). To a new developer, how would they know which is which?Also there is the missing array_find_value_and_key() method. Because why should we be limited to either matching the key OR the value?
Hi,
You are right about speed penalty for using those functions over simple
loops, however if we would stick to that point of view, we should
deprecate and remove array_filter, array_map, array_walk, array_u...
Proposed functions are not intended for developers working on large
arrays with speed constraints, but for simple usecases where (at least
for some people) readability will be improved by reducing 6 lines of
code to just 1.
"find" is consistent with names of the same function in other languages
as Tim has pointed in his email yesterday.
I leally do not see many uses for array_find_value_and_key, however - as
I you can see in my example implementations - condition is only checked
for the values of the array. We could have a nice family of
array_find_... functions including adding array_find_by_key and
array_find_key_by_key, array_find_by_value_and_key and
array_find_key_by_value_and_key... ;) or better discuss whether we
should pass both key and value to callback like below (order of the
arguments for the callback is to be discussed) or use flags like in
array_filter to decide what do we want to pass
function array_find(callable $callback, array $array)
{
foreach ($array as $key => $value) {
if (call_user_func($callback, $value, $key) === true) {
return $row;
}
}
return null;
}
vs
function array_find(callable $callback, array $array, int $mode = 0)
{
...
}
Best regards,
Janusz
Le 02/06/2023 à 10:57, Janusz Szczypka a écrit :
You are right about speed penalty for using those functions over
simple loops, however if we would stick to that point of view, we
should deprecate and remove array_filter, array_map, array_walk,
array_u...
I'm not sure they deserve deprecation, but I think that proposal may be
the right time to talk about adding a real iterable API in PHP core for
every one to use, a complete and consistent one, that would work on all
traversable data structures, https://github.com/nikic/iter is perfect in
my opinion for a good start, and would really deserve to be in SPL, and
maintained along with core, and be usable without any composer dependencies.
PHP is really lacking a complete enumerable / iterable / traversable
API. Maybe this is time to design and add one ?
--
Pierre