Re: Add is_vectorlike($array) function
| From: | Ryan Pallas | Date: | Fri, 05 May 2017 21:19:51 +0000 |
| Subject: | Re: Add is_vectorlike($array) function | ||
| References: | 1 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-98976@lists.php.net to get a copy of this message | ||
On Tue, May 2, 2017 at 3:13 AM, Jesse Schalken <me@jesseschalken.com> wrote:
> Related to the optimisation made by Sara Golemon here:
>
> https://github.com/php/php-src/commit/c74bc87c74f48bc55541b3bf2fc67d
> 595f58a3b5
>
> I often define a function like this, which checks if an array is "vector
> like" i.e. has keys 0,1,2..N:
>
> function is_vectorlike(array $a): bool {
> $i = 0;
> foreach ($a as $k => $v) {
> if ($k !== $i++) {
> return false;
> }
> }
> return true;
> }
>
> The problem is that this function is O(n), but in PHP7 an array that is
> vector-like is likely to be packed and without holes (HT_IS_PACKED(x) &&
> HT_IS_WITHOUT_HOLES(x)), in which case it is known to be vector-like
> without needing to iterate over it, but PHP code can't check for this (nor
> should it be able to, since it's really an implementation detail).
>
> Would it be a good idea to define this is_vectorlike() function in the PHP
> runtime, so it can short circuit to return true on packed arrays without
> holes? The above code would be a suitable polyfill.
>
I just read this thread and am wondering what exactly is the use case? Like
are you going to do something if it is vector-like, and do something
different (or not do anything at all) if it's not vector-like? I mean, if
you have to crawl it, and need a vector, why not just call array_values and
guarantee you have a vector?
Also, given the implementation above, why does the array have to be ksorted
correctly to count? Specifically, why isn't this array considered vector
like?
$arr = [
1=> 1,
0=> 0,
];
Wouldn't the following be a better test?
function is_vectorlike(array $a): bool {
$l = count($a);
for (i=0; $i<$l, $i++) {
if (!array_key_exists($i, $a)) {
return false;
}
}
return true;
}