使用 RecursiveDirectoryIterator 对目录列表进行排序

发布于 2024-09-03 16:56:19 字数 418 浏览 8 评论 0原文

我使用 RecursiveDirectoryIteratorRecursiveIteratorIterator 使用如下代码构建文件列表树。我需要对列表进行排序 - 目录然后按字母顺序排列文件,或者仅按字母顺序排列。

谁能告诉我如何对文件列表进行排序?

$dir_iterator = new RecursiveDirectoryIterator($groupDirectory);
$iterator = new RecursiveIteratorIterator($dir_iterator, RecursiveIteratorIterator::SELF_FIRST);
foreach ($iterator as $file) {
    // do stuff with $file
}

I'm using RecursiveDirectoryIterator and RecursiveIteratorIterator to build a file listing tree using code like below. I need to the list to be sorted - either directories then files alphabetically, or just alphabetically.

Can anyone tell me how to sort the file list?

$dir_iterator = new RecursiveDirectoryIterator($groupDirectory);
$iterator = new RecursiveIteratorIterator($dir_iterator, RecursiveIteratorIterator::SELF_FIRST);
foreach ($iterator as $file) {
    // do stuff with $file
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

七色彩虹 2024-09-10 16:56:19

有多个可用选项,您可以使用它们以一种或另一种方式对迭代器进行排序。最好的选择在很大程度上取决于您想要如何操作迭代器内容、您想从迭代器中获得什么以及您真正想要/需要多少迭代器。

方法会有所不同;使用 SplHeap(或 MinMax 变体)、SplPriorityQueue(可能用于文件大小等内容)等类)或者只是将迭代器包装在像 ArrayObject 之类的东西中,它可以对其自己的内容进行排序。

我将使用 SplHeap 作为示例。由于您想按字母顺序排列 RecursiveDirectoryIterator 的全部内容,因此可以使用如下所示的内容:

class ExampleSortedIterator extends SplHeap
{
    public function __construct(Iterator $iterator)
    {
        foreach ($iterator as $item) {
            $this->insert($item);
        }
    }
    public function compare($b,$a)
    {
        return strcmp($a->getRealpath(), $b->getRealpath());
    }
}

$dit = new RecursiveDirectoryIterator("./path/to/files");
$rit = new RecursiveIteratorIterator($dit);
$sit = new ExampleSortedIterator($rit);
foreach ($sit as $file) {
    echo $file->getPathname() . PHP_EOL;
}

排序顺序按字母顺序排列,混合文件和文件夹:

./apple
./apple/alpha.txt
./apple/bravo.txt
./apple/charlie.txt
./artichoke.txt
./banana
./banana/aardvark.txt
./banana/bat.txt
./banana/cat.txt
./beans.txt
./carrot.txt
./cherry
./cherry/amy.txt
./cherry/brian.txt
./cherry/charlie.txt
./damson
./damson/xray.txt
./damson/yacht.txt
./damson/zebra.txt
./duck.txt

There are multiple options available, which you can use to sort an iterator in one way or another. The best option would depend a great deal on precisely how you want to manipulate the iterator contents, what you want to get out of the iterator and indeed how much or little of the iterator you really want/need.

Approaches would vary; making use of classes like SplHeap (or Min, Max varieties), SplPriorityQueue (maybe for things like file size) or just wrapping your iterator in something like ArrayObject which can sort its own contents.

I'll use an SplHeap as an example. Since you want to arrange the entire contents of the RecursiveDirectoryIterator alphabetically then something like the following could be used:

class ExampleSortedIterator extends SplHeap
{
    public function __construct(Iterator $iterator)
    {
        foreach ($iterator as $item) {
            $this->insert($item);
        }
    }
    public function compare($b,$a)
    {
        return strcmp($a->getRealpath(), $b->getRealpath());
    }
}

$dit = new RecursiveDirectoryIterator("./path/to/files");
$rit = new RecursiveIteratorIterator($dit);
$sit = new ExampleSortedIterator($rit);
foreach ($sit as $file) {
    echo $file->getPathname() . PHP_EOL;
}

The sorting order is alphabetical, mixing files and folders:

./apple
./apple/alpha.txt
./apple/bravo.txt
./apple/charlie.txt
./artichoke.txt
./banana
./banana/aardvark.txt
./banana/bat.txt
./banana/cat.txt
./beans.txt
./carrot.txt
./cherry
./cherry/amy.txt
./cherry/brian.txt
./cherry/charlie.txt
./damson
./damson/xray.txt
./damson/yacht.txt
./damson/zebra.txt
./duck.txt
_蜘蛛 2024-09-10 16:56:19

使用迭代器本身是不可能实现这一点的。我在 SO 上的某个地方看到了 Iterator 类的扩展,它可以进行排序,但模糊地记得它遇到了麻烦。

也许这个问题的答案有帮助,即使它们指出远离迭代器?

更新这里是对你的问题的欺骗,其中包含一些答案 - 但不可否认,数量不多!

This is not possible using the Iterator itself. I have seen an extension to the Iterator class somewhere on SO that did sorting but remember hazily to have had trouble with it.

Maybe the answers to this question help, even though they point away from the Iterator?

Update: Here is a dupe to your question with some answers - admittedly not many, though!

中性美 2024-09-10 16:56:19

Sönke Ruempler 有一个很好的解决方案:

class SortingIterator implements IteratorAggregate
{

        private $iterator = null;

        public function __construct(Traversable $iterator, $callback)
        {
                if (!is_callable($callback)) {
                        throw new InvalidArgumentException('Given callback is not callable!');
                }

                $array = iterator_to_array($iterator);
                usort($array, $callback);
                $this->iterator = new ArrayIterator($array);
        }


        public function getIterator()
        {
                return $this->iterator;
        }
}

来源:https://ruempler.eu/2008/08/09/php-sortingiterator/

Sönke Ruempler has a great solution:

class SortingIterator implements IteratorAggregate
{

        private $iterator = null;

        public function __construct(Traversable $iterator, $callback)
        {
                if (!is_callable($callback)) {
                        throw new InvalidArgumentException('Given callback is not callable!');
                }

                $array = iterator_to_array($iterator);
                usort($array, $callback);
                $this->iterator = new ArrayIterator($array);
        }


        public function getIterator()
        {
                return $this->iterator;
        }
}

Source: https://ruempler.eu/2008/08/09/php-sortingiterator/

暗藏城府 2024-09-10 16:56:19

黑客方式:

$files = new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator($dir, $ropts));
$files2=[];
foreach($files as $f)$files2[] = (string)$f;
natcasesort($files2);
$files = $files2; #now filelist sorted

hacky way:

$files = new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator($dir, $ropts));
$files2=[];
foreach($files as $f)$files2[] = (string)$f;
natcasesort($files2);
$files = $files2; #now filelist sorted
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文