Created
March 3, 2012 11:35
-
-
Save Thinkscape/1965669 to your computer and use it in GitHub Desktop.
A benchmark of several methods for checking if PHP array is associative
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
if(!isset($argv[1])){ | |
echo "Usage: ".$argv[0]." (number of iterations)\n"; | |
exit(1); | |
} | |
/** | |
* Arrays to check | |
*/ | |
$tests = array( | |
array(array( | |
'foo' => 'bar', | |
)), | |
array(array( | |
'bar', | |
'foo' => 'bar', | |
'baz', | |
)), | |
array(null), | |
array(true), | |
array(false), | |
array(0), | |
array(1), | |
array(0.0), | |
array(1.0), | |
array('string'), | |
array(array(0, 1, 2)), | |
array(new stdClass), | |
array_fill(0,1000,uniqid()), // big numeric array | |
array_fill_keys(range(2,1000,3),uniqid()), // big misaligned numeric array (=associative) | |
array_fill_keys( // big associative array | |
str_split( | |
str_repeat(uniqid('',true),100), | |
3 | |
), | |
true | |
) | |
); | |
$iterations = (int)$argv[1]; | |
/** | |
* Common methods to check associative array | |
*/ | |
$methods = array( | |
'method1 (array_values check)' => | |
function($array){ | |
return (array_values($array) !== $array); | |
}, | |
'method2 (array_keys comparison)' => | |
function($array){ | |
$array = array_keys($array); return ($array !== array_keys($array)); | |
}, | |
'method3 (array_filter of keys)' => | |
function($array){ | |
return count(array_filter(array_keys($array), 'is_string')) > 0; | |
} | |
); | |
/** | |
* Perform benchmark on each method | |
*/ | |
foreach($methods as $name=>$func){ | |
echo "Testing $name - $iterations iterations\n"; | |
$time = microtime(true); | |
for($x=0;$x<$iterations;$x++){ | |
foreach($tests as $array){ | |
$func($array); | |
} | |
} | |
/** | |
* Show results | |
*/ | |
$totalTime = (microtime(true) - $time); | |
$avgTime = $totalTime / ($iterations * count($tests)); | |
echo " Total time: ".number_format($totalTime,5,'.',' ')." s\n"; | |
echo " Average : ".number_format($avgTime*1000,5,'.',' ')." ms / test \n"; | |
echo "\n"; | |
} | |
Hi, I just came with an idea of a is_associative_array function if you are still open to contributions:
<?php
function is_associative_array( array &$a ): bool {
$l = count( $a );
for ( $i = 0; $i < $l; $i++ ) {
if ( key( $a ) !== $i ) {
return true;
}
next( $a );
}
return false;
}
Tell me about it!
Hi, I just came with an idea of a is_associative_array function if you are still open to contributions:
<?php function is_associative_array( array &$a ): bool { $l = count( $a ); for ( $i = 0; $i < $l; $i++ ) { if ( key( $a ) !== $i ) { return true; } next( $a ); } return false; }
Tell me about it!
i just tested your method and it is way worse than all others... sorry :)
source: https://gist.github.com/oriadam/5e8424608fb3f8d70ec3e9ae344dbf8f
Testing 10000 iterations on PHP version 7.3.25
if (array_key_first($array)!==0) return true; return array_values($array) !== $array;
Total time: 0.26179 s
Average : 0.00175 ms / test
return array_values($array) !== $array;
Total time: 0.23978 s
Average : 0.00160 ms / test
return range(0,count($array)) !== array_keys($array);
Total time: 0.44664 s
Average : 0.00298 ms / test
return array_keys($array); return ($array !== array_keys($array));
Total time: 0.50882 s
Average : 0.00339 ms / test
return count(array_filter(array_keys($array), "is_string")) > 0;
Total time: 3.99202 s
Average : 0.02661 ms / test
foreach...$i++
Total time: 1.23879 s
Average : 0.00826 ms / test
for...key...next
Total time: 7.73038 s
Average : 0.05154 ms / test
check this out:
$methods = [
// [...]
'method4 (revision of method1, with php8.1 fn)' =>
function ($array) {
return (array_is_list($array) === false);
},
'method5 (json_encode output parsing with array_is_list - php>=8.1)' =>
static function ($array) {
// consider empty, and [0, 1, 2, ...] sequential
if (empty($array) || array_is_list($array)) {
return false;
}
// first scenario:
// [ 1 => [*any*] ]
// [ 'a' => [*any*] ]
foreach ( $array as $key => $value ) {
if (is_array($value)) {
return true;
}
}
// second scenario: read the json string
$jsonNest = json_encode($array, JSON_THROW_ON_ERROR);
return str_contains($jsonNest, '{');
},
'method6 (json_encode output parsing - php=8.0)' =>
static function ($array) {
if (empty($array) || array_values($array) !== $array) { return false; }
foreach ( $array as $key => $value ) { if (is_array($value)) { return true; } }
$jsonNest = json_encode($array, JSON_THROW_ON_ERROR);
return str_contains($jsonNest, '{');
},
];
Results
Testing method1 (array_values check) - 10000 iterations
Total time: 0.60444 s
Average : 0.00403 ms / test
Testing method2 (array_keys comparison) - 10000 iterations
Total time: 0.32689 s
Average : 0.00218 ms / test
Testing method3 (array_filter of keys) - 10000 iterations
Total time: 2.22523 s
Average : 0.01483 ms / test
Testing method4 (revision of method1, with php8.1 fn) - 10000 iterations
Total time: 0.09834 s
Average : 0.00066 ms / test
Testing method5 (json_encode output parsing with array_is_list - php>=8.1) - 10000 iterations
Total time: 0.47469 s
Average : 0.00316 ms / test
Testing method6 (json_encode output parsing - php<=8.0) - 10000 iterations
Total time: 1.01134 s
Average : 0.00674 ms / test
Anyone curious about the benchmark without the static closure?
Testing method5 (json_encode output parsing with array_is_list - php>=8.1) - 10000 iterations
Total time: 1.08914 s
Average : 0.00726 ms / test
Testing method6 (json_encode output parsing - php=8.0) - 10000 iterations
Total time: 4.92953 s
Average : 0.03286 ms / test
They are much slower!
other methods perform the same instead. Somebody can explain me why?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Method 1 is even more faster with PHP 7.2:
Testing method1 (array_values check) - 10000 iterations
Total time: 0.02857 s
Average : 0.00019 ms / test (!)
Testing method2 (array_keys comparison) - 10000 iterations
Total time: 0.19137 s
Average : 0.00128 ms / test
Testing method3 (array_filter of keys) - 10000 iterations
Total time: 0.48394 s
Average : 0.00323 ms / test
Testing method4 (foreach typecast) - 10000 iterations
Total time: 0.41342 s
Average : 0.00276 ms / test