简体   繁体   中英

PHP: usort files / speed

I am looking for a way to sort an array of objects based on two factors. This is my current usort implementation:

usort($contents, function($a, $b) {
    $aN = $a->getName();
    $bN = $b->getName();

    $aD = $a->isDirectory();
    $bD = $b->isDirectory();

    switch(true) {
        case  $aD && !$bD: return -1;
        case !$aD &&  $bD: return +1;
        default:
            return strcmp($aN, $bN); // Edited
    }
});

As you might have guessed, the objects represent files, however for this example, only the ->getName and ->isDirectory methods are relevant.

This example I have create does work, however I tested it on a collection of 9000 files, and this block alone increased the time of the general process from 1 second to around 3.

The sorting it is doing is fairly simple:

  • Directories first in alphanumerical order.
  • Files second in alphanumerical order.

I am looking for a way to improve it, or find an alternative.

If it is to anyones interest, this is the source of the $contents array:

$path = $this->compute($path);
$dir  = opendir($path);

$contents = array();

while(false !== $name = readdir($dir)) {
    if($name == '.' || $name == '..') {
        continue;
    }

    $contents[] = new LocalFile($this->directory, sprintf('%s/%s', $path, $name));
}

return $contents;

However this process takes very little time, I would be interested to discover that sorting can be accomplishing during the reading of a directory.

Side note, I have read I can use DirectoryIterator by extending it and performing comparisons, but I am not sure that is a lot different to what I am doing right now.

Your sorting logic could be simplified to just this:

    if (($a_isdir = $a->isDirectory()) != $b->isDirectory()) {
        // either a is directory and b is not, or the other way around
        return $a_isdir ? -1 : 1;
    }

    // a and b are either both directories or files
    // compare normally
    return strcmp($a->getName(), $b->getName());

Additionally, as mentioned by Mark, you can extend SplHeap by implementing the above logic inside ::compare($a, $b) and have the list of objects sorted as you insert them.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM