|
at 2005-05-29
in General
by friebe
(1 comments)
PHP's handling of arrays is superb: It's easy to create them. It's easy to manipulate them (there's about a gazillion functions over here). It's easy to access them. Their hashing algorithm is fast as a lightning. Aah: Hashing. Hashes and arrays are indistinguishable in PHP. And that's where the problem lies when communicating with languages where this is not the case. Hrm, you may think: $a= array(1, 2, 3); is numeric and $a= array("key" => "val"); is a hash, for sure. But how do we find out programmatically? I stumbled upon a piece of sourcecode reading:
<?php if (array_keys($a) === range(0, sizeof($a)- 1)) { } ?> "What's the problem - this looks like a very elegant solution?", you may think. Well, the problem is that for large arrays, it creates two new arrays of the same size as the passed array, one with the keys and one with range() and the compares them (which internally goes over each element of both lists and checks them for equality).
What I was interested in was finding out if there's a faster solution (except, of course, writing a builtin function). Therefore, I wrote a small script containing various methods of finding out whether an array is numeric. These are the different strategies:
#1: The code snippet from above
<?php class KeyRangeStrategy extends Object {
function execute($a) { return is_array($a) && (array_keys($a) === range(0, sizeof($a)- 1)); } } ?> #2: Use key() and next()
<?php class KeyNextStrategy extends Object {
function execute($a) { if (!is_array($a)) return FALSE; $i= 0; do { if (key($a) !== $i++) return FALSE; } while (FALSE !== next($a)); return TRUE; } } ?> #3: Use a for() loop
<?php class ForLoopStrategy extends Object {
function execute($a) { if (!is_array($a)) return FALSE; for ($k= array_keys($a), $s= sizeof($k), $i= 0; $i < $s; $i++) { if ($k[$i] !== $i) return FALSE; } return TRUE; } } ?> #4: Use list() and each()
<?php class ListEachStrategy extends Object {
function execute($a) { if (!is_array($a)) return FALSE; $i= 0; while (list($key, )= each($a)) { if ($key !== $i++) return FALSE; } return TRUE; } } ?> #5: Use foreach()
<?php class ForeachStrategy extends Object {
function execute($a) { if (!is_array($a)) return FALSE; $i= 0; foreach (array_keys($a) as $k) { if ($k !== $i++) return FALSE; } return TRUE; } } ?> To test the strategies, I used the following test data:
- A small array with numeric values
- An array with 1000 elements
- An array containing two strings
- An array containing a wrong key
- A hash
The script's sourcecode is available here, the results here.
And the winner is: foreach()! Although it does not perform as well on the small arrays, it is nearly twice as fast as the KeyRange strategy on the array created with range(1, 1000);. Also interesting is the fact that the for() loop is slower than foreach. This is due to the fact that the array access whithin the loop ($k[$i]) takes more time than simply reading a local variable.
|
Subscribe
You can subscribe to the XP framework's news by using RSS syndication.
CategoriesNews General PHP5 Announcements RFCs Further reading Examples Editorial EASC Experiments Unittests Databases
RelatedFind related articles by a search for «Numeric».
|