web-dev-qa-db-ja.com

RecursiveIteratorIteratorはPHPでどのように機能しますか?

RecursiveIteratorIteratorはどのように機能しますか?

PHPマニュアルには、ドキュメントや説明があまりありません。IteratorIteratorRecursiveIteratorIteratorの違いは何ですか?]

82
varuog

IteratorIteratorRecursiveIteratorIteratorの違いは何ですか?

これら2つのイテレータの違いを理解するには、まず、使用される命名規則と「再帰」イテレータの意味について少し理解する必要があります。

再帰および非再帰イテレーター

PHPには、ArrayIteratorFilesystemIteratorなどの非「再帰」イテレーターがあります。 RecursiveArrayIteratorRecursiveDirectoryIteratorなどの「再帰的な」反復子もあります。後者にはドリルダウンできるメソッドがありますが、前者にはありません。

これらのイテレータのインスタンスが、再帰的なものであってもそれ自体でループされる場合、ネストされた配列またはサブディレクトリを持つディレクトリをループしても、値は「トップ」レベルからのみ取得されます。

再帰イテレーターimplement再帰動作(hasChildren()getChildren()を介して)でなくexploitそれ。

再帰イテレータを「再帰可能な」イテレータと考える方が良いかもしれません。それらはabilityを再帰的に繰り返しますが、単に1つのインスタンスを反復処理するだけです。これらのクラスのうち、それは行いません。再帰的な動作を活用するには、読み続けてください。

RecursiveIteratorIterator

ここで、RecursiveIteratorIteratorが再生されます。通常のフラットなループで構造にドリルダウンするような方法で、「再帰」イテレーターを呼び出す方法に関する知識があります。再帰的な動作を実行します。基本的に、反復子内の各値をステップオーバーし、再帰するかどうかを確認する「子」があるかどうかを確認し、それらの子のコレクションに出入りする作業を行います。 RecursiveIteratorIteratorのインスタンスをforeachに貼り付け、it構造に潜り込む必要がないようにします。

RecursiveIteratorIteratorが使用されなかった場合、「再帰的」イテレーターのhasChildren()をチェックし、getChildren()を使用して、再帰的動作を活用する独自の再帰ループを作成する必要があります。 。

これがRecursiveIteratorIteratorbriefの概要ですが、IteratorIteratorとはどう違いますか?さて、あなたは基本的にと同じ種類の質問をしていますが、子猫と木との違いは何ですか?両方が同じ百科事典に登場するからです(または反復子の場合は手動)は、2つを混同する必要があるという意味ではありません。

IteratorIterator

IteratorIteratorの仕事は、任意のTraversableオブジェクトを取得し、Iteratorインターフェイスを満たすようにラップすることです。これを使用すると、非反復オブジェクトに反復子固有の動作を適用できるようになります。

実用的な例を挙げると、DatePeriodクラスはTraversableですが、Iteratorではありません。そのため、foreach()を使用してその値をループできますが、フィルタリングなど、通常イテレーターで行うことはできません。

[〜#〜] task [〜#〜]:次の4週間の月曜日、水曜日、金曜日をループします。

はい、これはforeachDatePeriod- ingし、ループ内でif()を使用することで簡単です。しかし、それはこの例のポイントではありません!

$period = new DatePeriod(new DateTime, new DateInterval('P1D'), 28);
$dates  = new CallbackFilterIterator($period, function ($date) {
    return in_array($date->format('l'), array('Monday', 'Wednesday', 'Friday'));
});
foreach ($dates as $date) { … }

CallbackFilterIteratorIteratorインターフェイスを実装するクラスのインスタンスを予期するため、上記のスニペットは機能しませんが、DatePeriodはそうしません。ただし、それはTraversableなので、IteratorIteratorを使用することで簡単にその要件を満たすことができます。

$period = new IteratorIterator(new DatePeriod(…));

ご覧のとおり、これにはnothingイテレータクラスの繰り返しや再帰に関係なく、IteratorIteratorRecursiveIteratorIterator

概要

RecursiveIteraratorIteratorRecursiveIterator(「再帰的」イテレーター)を反復処理するためのもので、利用可能な再帰的動作を活用します。

IteratorIteratorは、Iterator動作を非反復子、Traversableオブジェクトに適用するためのものです。

30
salathe

RecursiveDirectoryIteratorは、ファイル名だけでなく、パス名全体を表示します。残りはよさそうだ。これは、ファイル名がSplFileInfoによって生成されるためです。代わりにベース名として表示する必要があります。望ましい出力は次のとおりです。

$path =__DIR__;
$dir = new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS);
$files = new RecursiveIteratorIterator($dir,RecursiveIteratorIterator::SELF_FIRST);
while ($files->valid()) {
    $file = $files->current();
    $filename = $file->getFilename();
    $deep = $files->getDepth();
    $indent = str_repeat('│ ', $deep);
    $files->next();
    $valid = $files->valid();
    if ($valid and ($files->getDepth() - 1 == $deep or $files->getDepth() == $deep)) {
        echo $indent, "├ $filename\n";
    } else {
        echo $indent, "└ $filename\n";
    }
}

出力:

tree
 ├ dirA
 │ ├ dirB
 │ │ └ fileD
 │ ├ fileB
 │ └ fileC
 └ fileA
0
javad shariaty