Reputation: 5416
I've stumbled on what would be the fastest way to check whether or not all elements in an array are of the same type, in PHP. After browsing StackOverflow for different methods to do this, I decided to check which of them is faster. I've tested different approaches (see my self answer below).
Hope this helps.
EDIT
After reading about what "micro-optimization" is, it seems that this is a micro-optimization question. I hadn't heard about this word before 'cause, to my surprise, I always code in a "micro-optimized" way as long as good code readability is kept. Perhaps my roots in data processing programming in the embedded world have turned my mind to some sort of code micro-optimizer :D
Upvotes: 0
Views: 456
Reputation: 212402
$v = range(1, 100000);
$v[]=false; //Put a non-integer element at the end
$testf = 'is_int';
$result = array_reduce (
$v,
function($return, $value) use ($testf) {
return $return && $testf($value);
},
true
);
var_dump($result);
EDIT
Results on my laptop:
PHP 5.4.7
TEST isArrayOf_1: result = fail, t = 0.033294200897217
TEST isArrayOf_2: result = fail, t = 0.10196995735168
TEST isArrayOf_3: result = fail, t = 0.052531957626343
TEST isArrayOf_4: result = fail, t = 0.079360961914062
TEST isArrayOf_1: result = fail, t = 0.0085389614105225
TEST isArrayOf_2: result = fail, t = 0.0083901882171631
TEST isArrayOf_3: result = fail, t = 0.044848918914795
TEST isArrayOf_4: result = fail, t = 0.035619020462036
PHP 5.4.21
TEST isArrayOf_1: result = fail, t = 0.032476902008057
TEST isArrayOf_2: result = fail, t = 0.098520040512085
TEST isArrayOf_3: result = fail, t = 0.052137136459351
TEST isArrayOf_4: result = fail, t = 0.074975967407227
TEST isArrayOf_1: result = fail, t = 0.0085029602050781
TEST isArrayOf_2: result = fail, t = 0.0084490776062012
TEST isArrayOf_3: result = fail, t = 0.044224977493286
TEST isArrayOf_4: result = fail, t = 0.035413026809692
PHP 5.3.27
TEST isArrayOf_1: result = fail, t = 0.036087036132812
TEST isArrayOf_2: result = fail, t = 0.11226201057434
TEST isArrayOf_3: result = fail, t = 0.053704977035522
TEST isArrayOf_4: result = fail, t = 0.078150987625122
TEST isArrayOf_1: result = fail, t = 0.0088350772857666
TEST isArrayOf_2: result = fail, t = 0.008991003036499
TEST isArrayOf_3: result = fail, t = 0.045068979263306
TEST isArrayOf_4: result = fail, t = 0.039391994476318
PHP 5.5.5
TEST isArrayOf_1: result = fail, t = 0.029086112976074
TEST isArrayOf_2: result = fail, t = 0.057933807373047
TEST isArrayOf_3: result = fail, t = 0.03432297706604
TEST isArrayOf_4: result = fail, t = 0.052994012832642
TEST isArrayOf_1: result = fail, t = 0.0085070133209229
TEST isArrayOf_2: result = fail, t = 0.0085380077362061
TEST isArrayOf_3: result = fail, t = 0.024166107177734
TEST isArrayOf_4: result = fail, t = 0.034998178482056
Upvotes: 2
Reputation: 5416
PHP code:
//Approach 1: pass array and the name of a PHP type
function isArrayOf_1($v, $phptype) {
if (is_array($v)) {
foreach ($v as $elem) if (gettype($elem) != $phptype) return FALSE;
return TRUE;
}
return FALSE;
}
//Approach 2: pass array and the name of a PHP type-check function (e.g.: is_int())
function isArrayOf_2($v, $testf) {
if (is_array($v)) {
foreach ($v as $elem) if (!call_user_func($testf, $elem)) return FALSE;
return TRUE;
}
return FALSE;
}
//Approach 3: pass array and the name of a PHP type-check function (e.g.: is_int())
function isArrayOf_3($v, $testf) {
if (is_array($v)) {
if (count($v) != count(array_filter($v, $testf))) return FALSE;
return TRUE;
}
return FALSE;
}
//Approach 4: pass array and the name of a PHP type-check function (e.g.: is_int())
function isArrayOf_4($v, $testf) {
if (is_array($v)) {
return array_reduce (
$v,
function($return, $value) use ($testf) {
return $return && $testf($value);
},
true
);
}
return FALSE;
}
//Number of tested functions
$TEST_FUNCTIONS = 4;
//Test data
$v = range(1, 100000);
$v[]=false; //Put a non-integer element at the end
//Tests
$tests = array(
array('integer', 'is_int', 'is_int'), //Successful check test
array('boolean', 'is_bool', 'is_bool') //Wrong check test
);
foreach ($tests as $test) {
for ($i = 1; $i <= $TEST_FUNCTIONS; $i++) {
$start = microtime(true);
$res = call_user_func("isArrayOf_$i", $v, $test[$i-1]);
$t = microtime(true) - $start;
echo "TEST isArrayOf_$i: result = ".($res?'success':'fail').", t = $t<br/>";
}
echo "<br/>";
}
OUTPUT
TEST isArrayOf_1: result = fail, t = 0.13473296165466
TEST isArrayOf_2: result = fail, t = 0.22269797325134
TEST isArrayOf_3: result = fail, t = 0.074767112731934
TEST isArrayOf_4: result = fail, t = 0.91770792007446
TEST isArrayOf_1: result = fail, t = 0.017352104187012
TEST isArrayOf_2: result = fail, t = 0.015971899032593
TEST isArrayOf_3: result = fail, t = 0.058960914611816
TEST isArrayOf_4: result = fail, t = 0.75518012046814
We can see that if wrong values are found late in the array, approach 3 performs the best. However if wrong values appear early in the array, then approaches 1 and 2 are the winners. We also see that approach 3 behaves similar in both cases whereas the other two have such different execution times. The worst approach seems to be #4... Any ideas of why?
So, IMHO, approach 3 is the one I would choose to check whether or not all elements in an array are of a given type.
Upvotes: 1