- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
怎么样RecursiveIteratorIterator
工作?
PHP 手册没有太多记录或解释。 IteratorIterator
有什么区别和 RecursiveIteratorIterator
?
最佳答案
RecursiveIteratorIterator
是混凝土 Iterator
实现 tree traversal .它使程序员能够遍历实现 RecursiveIterator
的容器对象。接口(interface),见Iterator in Wikipedia迭代器的一般原理、类型、语义和模式。
与 IteratorIterator
不同这是一个混凝土 Iterator
以线性顺序实现对象遍历(默认情况下在其构造函数中接受任何类型的 Traversable
),RecursiveIteratorIterator
允许遍历有序对象树中的所有节点,其构造函数采用 RecursiveIterator
.
简而言之:RecursiveIteratorIterator
允许你遍历一棵树,IteratorIterator
允许您遍历列表。我很快就会用下面的一些代码示例来说明这一点。
从技术上讲,这是通过遍历节点的所有子节点(如果有)来打破线性的。这是可能的,因为根据定义,节点的所有子节点都是 RecursiveIterator
.顶级Iterator
然后在内部堆叠不同的 RecursiveIterator
s 按它们的深度并保持一个指向当前事件子节点的指针 Iterator
为遍历。
这允许访问树的所有节点。
基本原理与 IteratorIterator
相同: 一个接口(interface)指定了迭代的类型,基迭代器类是这些语义的实现。与下面的示例进行比较,使用 foreach
进行线性循环您通常不会过多考虑实现细节,除非您需要定义一个新的 Iterator
(例如,当某些具体类型本身没有实现 Traversable
时)。
对于递归遍历 - 除非您不使用预定义的 Traversal
已经具有递归遍历迭代 - 您通常需要实例化现有 RecursiveIteratorIterator
迭代,甚至编写一个递归遍历迭代,它是 Traversable
您自己可以使用 foreach
进行这种类型的遍历迭代.
Tip: You probably didn't implement the one nor the other your own, so this might be something worth to do for your practical experience of the differences they have. You find a DIY suggestion at the end of the answer.
IteratorIterator
随便拿Traversable
用于线性遍历,RecursiveIteratorIterator
需要更具体的RecursiveIterator
在树上循环。 IteratorIterator
暴露其主要Iterator
通过 getInnerIerator()
, RecursiveIteratorIterator
提供当前事件子Iterator
只能通过那个方法。 IteratorIterator
完全不知道 parent 或 child 之类的事情,RecursiveIteratorIterator
也知道如何获取和遍历 child 。 IteratorIterator
不需要一堆迭代器,RecursiveIteratorIterator
有这样一个堆栈并且知道事件的子迭代器。 IteratorIterator
由于线性和别无选择,有其顺序,RecursiveIteratorIterator
可以选择进一步遍历,并且需要根据每个节点来决定(通过 mode per RecursiveIteratorIterator
决定)。 RecursiveIteratorIterator
拥有比 IteratorIterator
更多的方法. RecursiveIterator
是一种具体类型的迭代(循环树),它适用于自己的迭代器,即
RecursiveIterator
.这与
IteratorIerator
的基本原理相同,但迭代的类型不同(线性顺序)。
Traversable
这可以通过
Iterator
实现或
IteratorAggregate
.然后你可以用
foreach
.例如,某种三叉树遍历递归迭代对象以及容器对象的相应迭代接口(interface)。
Non-Recursive Recursive
============= =========
[tree] [tree]
├ dirA ├ dirA
└ fileA │ ├ dirB
│ │ └ fileD
│ ├ fileB
│ └ fileC
└ fileA
IteratorIterator
进行比较。它没有遍历目录树的递归。和
RecursiveIteratorIterator
如递归列表所示,它可以遍历树。
DirectoryIterator
实现
Traversable
允许
foreach
迭代它:
$path = 'tree';
$dir = new DirectoryIterator($path);
echo "[$path]\n";
foreach ($dir as $file) {
echo " ├ $file\n";
}
[tree]
├ .
├ ..
├ dirA
├ fileA
IteratorIterator
或
RecursiveIteratorIterator
.相反,它只是使用
foreach
在
Traversable
上运行界面。
foreach
默认情况下只知道名为线性顺序的迭代类型,我们可能希望明确指定迭代类型。乍一看,它似乎太冗长了,但为了演示目的(以及与
RecursiveIteratorIterator
的区别稍后更明显),让我们明确指定
IteratorIterator
来指定线性迭代类型。目录列表的迭代类型:
$files = new IteratorIterator($dir);
echo "[$path]\n";
foreach ($files as $file) {
echo " ├ $file\n";
}
$files
现在是
IteratorIterator
Traversable
的迭代类型
$dir
:
$files = new IteratorIterator($dir);
foreach
执行。 :
foreach ($files as $file) {
foreach
中使用的对象.在第一个示例中,它是
DirectoryIterator
在第二个例子中,它是
IteratorIterator
.这显示了迭代器具有的灵活性:您可以相互替换它们,代码在
foreach
中。继续按预期工作。
foreach
来完成这项工作我们需要一个不同类型的迭代器:
RecursiveIteratorIterator
.而那个只能迭代具有
RecursiveIterator
interface 的容器对象。 .
RecursiveIteratorIterator
一起使用.这种类的一个例子是
RecursiveDirectoryIterator
,这类似于
DirectoryIterator
的递归变体.
$dir = new RecursiveDirectoryIterator($path);
echo "[$path]\n";
foreach ($dir as $file) {
echo " ├ $file\n";
}
[tree]
├ tree\.
├ tree\..
├ tree\dirA
├ tree\fileA
RecursiveIterator
接口(interface),这还不够做
foreach
遍历整个目录树。这是
RecursiveIteratorIterator
的地方付诸行动。示例 4 显示了如何:
$files = new RecursiveIteratorIterator($dir);
echo "[$path]\n";
foreach ($files as $file) {
echo " ├ $file\n";
}
RecursiveIteratorIterator
而不仅仅是之前的
$dir
对象将使
foreach
以递归方式遍历所有文件和目录。然后列出所有文件,因为现在已经指定了对象迭代的类型:
[tree]
├ tree\.
├ tree\..
├ tree\dirA\.
├ tree\dirA\..
├ tree\dirA\dirB\.
├ tree\dirA\dirB\..
├ tree\dirA\dirB\fileD
├ tree\dirA\fileB
├ tree\dirA\fileC
├ tree\fileA
RecursiveIteratorIterator
能够以元素列表的形式遍历任何树状结构。因为有更多信息(比如迭代当前发生的级别),可以在迭代时访问迭代器对象,例如缩进输出:
echo "[$path]\n";
foreach ($files as $file) {
$indent = str_repeat(' ', $files->getDepth());
echo $indent, " ├ $file\n";
}
[tree]
├ tree\.
├ tree\..
├ tree\dirA\.
├ tree\dirA\..
├ tree\dirA\dirB\.
├ tree\dirA\dirB\..
├ tree\dirA\dirB\fileD
├ tree\dirA\fileB
├ tree\dirA\fileC
├ tree\fileA
foreach
只能表达这种线性,访问迭代器本身可以获得更多信息。
RecursiveIteratorIterator
它可以用构造函数设置。
RecursiveDirectoryIterator
删除点条目(
.
和
..
),因为我们不需要它们。但递归模式也将更改为在子元素(子目录中的文件和子子目录)之前先获取父元素(子目录)(
SELF_FIRST
):
$dir = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS);
$files = new RecursiveIteratorIterator($dir, RecursiveIteratorIterator::SELF_FIRST);
echo "[$path]\n";
foreach ($files as $file) {
$indent = str_repeat(' ', $files->getDepth());
echo $indent, " ├ $file\n";
}
[tree]
├ tree\dirA
├ tree\dirA\dirB
├ tree\dirA\dirB\fileD
├ tree\dirA\fileB
├ tree\dirA\fileC
├ tree\fileA
LEAVES_ONLY
(默认):只列出文件,不列出目录。 SELF_FIRST
(上图):列出目录,然后列出其中的文件。 CHILD_FIRST
(无示例):首先列出子目录中的文件,然后是目录。 LEAVES_ONLY CHILD_FIRST
[tree] [tree]
├ tree\dirA\dirB\fileD ├ tree\dirA\dirB\fileD
├ tree\dirA\fileB ├ tree\dirA\dirB
├ tree\dirA\fileC ├ tree\dirA\fileB
├ tree\fileA ├ tree\dirA\fileC
├ tree\dirA
├ tree\fileA
foreach
并完成。
Do It Yourself: Make the
RecursiveTreeIterator
Work Line by Line.
foreach
中有意证明的。迭代。在现实生活中,这自然属于
RecursiveIterator
.
RecursiveTreeIterator
,它负责缩进、前缀等。请参阅以下代码片段:
$dir = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS);
$lines = new RecursiveTreeIterator($dir);
$unicodeTreePrefix($lines);
echo "[$path]\n", implode("\n", iterator_to_array($lines));
RecursiveTreeIterator
旨在逐行工作,输出非常简单,有一个小问题:
[tree]
├ tree\dirA
│ ├ tree\dirA\dirB
│ │ └ tree\dirA\dirB\fileD
│ ├ tree\dirA\fileB
│ └ tree\dirA\fileC
└ tree\fileA
RecursiveDirectoryIterator
结合使用时它显示整个路径名,而不仅仅是文件名。其余的看起来不错。这是因为文件名是由
SplFileInfo
生成的.那些应该显示为基本名称。所需的输出如下:
/// Solved ///
[tree]
├ dirA
│ ├ dirB
│ │ └ fileD
│ ├ fileB
│ └ fileC
└ fileA
RecursiveTreeIterator
一起使用的装饰器类而不是
RecursiveDirectoryIterator
.它应该提供当前
SplFileInfo
的基本名称而不是路径名。最终的代码片段可能如下所示:
$lines = new RecursiveTreeIterator(
new DiyRecursiveDecorator($dir)
);
$unicodeTreePrefix($lines);
echo "[$path]\n", implode("\n", iterator_to_array($lines));
$unicodeTreePrefix
是附录中要点的一部分:自己动手:制作
RecursiveTreeIterator
一行一行地工作..
关于php - RecursiveIteratorIterator 在 PHP 中是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12077177/
我在 JavaScript 文件中运行 PHP,例如...... var = '';). 我需要使用 JavaScript 来扫描字符串中的 PHP 定界符(打开和关闭 PHP 的 )。 我已经知道使
我希望能够做这样的事情: php --determine-oldest-supported-php-version test.php 并得到这个输出: 7.2 也就是说,php 二进制检查 test.
我正在开发一个目前不使用任何框架的大型 php 站点。我的大问题是,随着时间的推移慢慢尝试将框架融入应用程序是否可取,例如在创建的新部件和更新的旧部件中? 比如所有的页面都是直接通过url服务的,有几
下面是我的源代码,我想在同一页面顶部的另一个 php 脚本中使用位于底部 php 脚本的变量 $r1。我需要一个简单的解决方案来解决这个问题。我想在代码中存在的更新查询中使用该变量。 $name)
我正在制作一个网站,根据不同的情况进行大量 PHP 重定向。就像这样...... header("Location: somesite.com/redirectedpage.php"); 为了安全起见
我有一个旧网站,我的 php 标签从 因为短标签已经显示出安全问题,并且在未来的版本中将不被支持。 关于php - 如何避免在 php 文件中写入
我有一个用 PHP 编写的配置文件,如下所示, 所以我想用PHP开发一个接口(interface),它可以编辑文件值,如$WEBPATH , $ACCOUNTPATH和 const值(value)观
我试图制作一个登录页面来学习基本的PHP,首先我希望我的独立PHP文件存储HTML文件的输入(带有表单),但是当我按下按钮时(触发POST到PHP脚本) )我一直收到令人不愉快的错误。 我已经搜索了S
我正在寻找一种让 PHP 以一种形式打印任意数组的方法,我可以将该数组作为赋值包含在我的(测试)代码中。 print_r 产生例如: Array ( [0] => qsr-part:1285 [1]
这个问题已经有答案了: 已关闭11 年前。 Possible Duplicate: What is the max key size for an array in PHP? 正如标题所说,我想知道
我正在寻找一种让 PHP 以一种形式打印任意数组的方法,我可以将该数组作为赋值包含在我的(测试)代码中。 print_r 产生例如: Array ( [0] => qsr-part:1285 [1]
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 9 年前。 Improve this ques
我在 MySQL 数据库中有一个表,其中存储餐厅在每个工作日和时段提供的菜单。 表结构如下: i_type i_name i_cost i_day i_start i_
我有两页。 test1.php 和 test2.php。 我想做的就是在 test1.php 上点击提交,并将 test2.php 显示在 div 中。这实际上工作正常,但我需要向 test2.php
我得到了这个代码。我想通过textarea更新mysql。我在textarea中回显我的MySQL,但我不知道如何更新它,我应该把所有东西都放进去吗,因为_GET模式没有给我任何东西,我也尝试_GET
首先,我是 php 的新手,所以我仍在努力学习。我在 Wordpress 上创建了一个表单,我想将值插入一个表(data_test 表,我已经管理了),然后从 data_test 表中获取所有列(id
我有以下函数可以清理用户或网址的输入: function SanitizeString($var) { $var=stripslashes($var); $va
我有一个 html 页面,它使用 php 文件查询数据库,然后让用户登录,否则拒绝访问。我遇到的问题是它只是重定向到 php 文件的 url,并且从不对发生的事情提供反馈。这是我第一次使用 html、
我有一个页面充满了指向 pdf 的链接,我想跟踪哪些链接被单击。我以为我可以做如下的事情,但遇到了问题: query($sql); if($result){
我正在使用 从外部文本文件加载 HTML/PHP 代码 $f = fopen($filename, "r"); while ($line = fgets($f, 4096)) { print $l
我是一名优秀的程序员,十分优秀!