Re: [RFC] array_search_range() function
| From: | Rowan Tommins [IMSoP] | Date: | Tue, 18 Aug 2026 17:01:35 +0000 |
| Subject: | Re: [RFC] array_search_range() function | ||
| References: | 1 2 3 4 5 6 7 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-132266@lists.php.net to get a copy of this message | ||
On 18 August 2026 16:08:58 BST, "Rowan Tommins [IMSoP]" <imsop.php@rwec.co.uk>
wrote:
>In fact, the simplest starting point would be no functions at all, just an optimised
>ArraySliceIterator. The actual search part is fairly easy to write in user code.
>
>Then in a separate RFC, add a new set of functions like "iter_search",
>"iter_any", etc, which would be useful with *any* iterator, not just this specific one.
Just to add, both ArraySliceIterator and iter_search can be implemented in less than twenty lines of
code each: <https://3v4l.org/HmYZV>
Which is great for adding them natively: users of older versions or who need to support multiple
versions can "polyfill" them to start using straight away, and then get more optimised
versions when they upgrade.
To be fair, the same is true of array_search_range: a memory-efficient user implementation is
simple, but can't be quite as time-efficient as an internal one because it can't use
optimisations based on the memory layout of the array. Only lightly tested, but covers all of the
proposed signature in about 30 lines: <https://3v4l.org/VAsXY>
For the archive, here's the sample implementations:
```
class ArraySliceIterator implements IteratorAggregate {
private LimitIterator $backingIterator;
public function __construct(array $array, int $offset, int $limit) {
$this->backingIterator = new LimitIterator(
new ArrayIterator($array),
$offset,
$limit
);
}
public function getIterator(): Traversable
{
return $this->backingIterator;
}
}
function iter_search(mixed $needle, iterable $haystack, bool $strict = false): int|string|false
{
foreach ( $haystack as $key => $value ) {
if (
( $strict && $value === $needle )
||
( ! $strict && $value == $needle )
) {
return $key;
}
}
return false;
}
function array_search_range(
mixed $needle,
array $haystack,
int $offset = 0,
?int $length = null,
bool $strict = false,
): int|string|false {
if ( $offset < 0 ) {
$offset = count($haystack) + $offset;
}
if ( $length < 0 ) {
$length = count($haystack) + $length - $offset;
}
$currentOffset = -1;
foreach ( $haystack as $key => $value ) {
$currentOffset++;
if ( $currentOffset < $offset ) {
continue;
}
if ( $length !== null && $currentOffset >= $offset + $length ) {
break;
}
if (
( $strict && $value === $needle )
||
( ! $strict && $value == $needle )
) {
return $key;
}
}
return false;
}
```
Regards,
Rowan Tommins
[IMSoP]