Performance improvements for NaturalSort

A combination of using isset() instead of count() or strlen(), caching the
chunkify function, and replacing is_numeric() with some comparisons
This commit is contained in:
Robin McCorkell 2015-01-20 12:40:18 +00:00
parent 5d8f1a1de3
commit 44c330aa5d
1 changed files with 10 additions and 7 deletions

View File

@ -12,6 +12,7 @@ namespace OC;
class NaturalSort {
private static $instance;
private $collator;
private $cache = array();
/**
* Split the given string in chunks of numbers and strings
@ -21,13 +22,15 @@ class NaturalSort {
private function naturalSortChunkify($t) {
// Adapted and ported to PHP from
// http://my.opera.com/GreyWyvern/blog/show.dml/1671288
if (isset($this->cache[$t])) {
return $this->cache[$t];
}
$tz = array();
$x = 0;
$y = -1;
$n = null;
$length = strlen($t);
while ($x < $length) {
while (isset($t[$x])) {
$c = $t[$x];
// only include the dot in strings
$m = ((!$n && $c === '.') || ($c >= '0' && $c <= '9'));
@ -40,6 +43,7 @@ class NaturalSort {
$tz[$y] .= $c;
$x++;
}
$this->cache[$t] = $tz;
return $tz;
}
@ -75,14 +79,13 @@ class NaturalSort {
// instead of ["test.txt", "test (2).txt"]
$aa = self::naturalSortChunkify($a);
$bb = self::naturalSortChunkify($b);
$alen = count($aa);
$blen = count($bb);
for ($x = 0; $x < $alen && $x < $blen; $x++) {
for ($x = 0; isset($aa[$x]) && isset($bb[$x]); $x++) {
$aChunk = $aa[$x];
$bChunk = $bb[$x];
if ($aChunk !== $bChunk) {
if (is_numeric($aChunk) && is_numeric($bChunk)) {
// test first character (character comparison, not number comparison)
if ($aChunk[0] >= '0' && $aChunk[0] <= '9' && $bChunk[0] >= '0' && $bChunk[0] <= '9') {
$aNum = (int)$aChunk;
$bNum = (int)$bChunk;
return $aNum - $bNum;
@ -90,7 +93,7 @@ class NaturalSort {
return self::getCollator()->compare($aChunk, $bChunk);
}
}
return $alen - $blen;
return count($aa) - count($bb);
}
/**