在上一篇文章中我们介绍了一些内置的迭代器的基本使用,在这一篇文章中我们将继续对另外的一些迭代器进行学习,他们是 RecursiveIterator(递归迭代器)系列迭代器,他们主要在需要对迭代器进行递归迭代时使用。
RecursiveIterator 迭代器
RecursiveIterator 迭代器接口继承 Iterator 迭代器,它为你的迭代器提供了递归访问的能力。使用它你可以很方便的对于一些多层数据行迭代处理,除了继承于 Iterator 迭代器的基本功能外,他还提供了 hasChildren 和 getChildren 两个方法。其中 getChildRen 的返回值必须是一个 RecursiveIterator 迭代器对象。
<?php
class AnRecursiveIterator implements RecursiveIterator
{
private $iterators;
private $index = 0;
public function __construct(array $iterators)
{
$this->iterators = $iterators;
}
public function current()
{
return $this->iterators[$this->index];
}
public function next()
{
$this->index++;
}
public function key()
{
return $this->index;
}
public function valid()
{
return isset($this->iterators[$this->index]);
}
public function rewind()
{
$this->index = 0;
}
/**
* 是否有子节点
* @return bool
*/
public function hasChildren()
{
return is_array($this->iterators[$this->index]);
}
/**
* 获取子节点迭代对象
* @return RecursiveIterator
*/
public function getChildren(): RecursiveIterator
{
return new self($this->iterators[$this->index]);
}
}
$iterator = new AnRecursiveIterator([1, 2, 3, 4, [5, 6, 7, [8, 9, 10, 11]]]);
function recursive(RecursiveIterator $iterator, $i = 0)
{
foreach ($iterator as $key => $item) {
echo str_repeat("\t", $i);
if ($iterator->hasChildren()) {
echo $key . ' has children' . PHP_EOL;
recursive($iterator->getChildren(), $i + 1);
} else {
echo $key . '.....' . $item . PHP_EOL;
}
}
}
recursive($iterator);
RecursiveArrayIterator 迭代器
RecursiveArrayIterator 迭代器继承自 ArrayIterator 并实现了 RecursiveIterator 接口,所以它兼具了 ArrayIterator 迭代器和 RecursiveIterator 迭代器的功能。使用它你可以更加灵活的对数据进行遍历迭代。
<?php
$iterator = new RecursiveArrayIterator([1, 2, 3, 4, 5, 7, 'test' => [11, 22, 33, 44, 55, 66]], RecursiveArrayIterator::CHILD_ARRAYS_ONLY);
function arrayRecursive(RecursiveArrayIterator $iterator, int $i = 0)
{
foreach ($iterator as $key => $item) {
echo str_repeat("\t", $i);
if ($iterator->hasChildren()) {
echo $key . ' has children' . PHP_EOL;
arrayRecursive($iterator->getChildren(), $i + 1);
} else {
echo $key . '.....' . $item . PHP_EOL;
}
}
}
arrayRecursive($iterator);
RecursiveCachingIterator 迭代器
RecursiveCachingIterator 迭代器是 CachingIterator 迭代器的子类并在此基础上实现了 Countable、ArrayAccess、OuterIterator、RecursiveIterator 接口。在 CachingIterator 迭代器基础上实现了递归迭代的能力。
<?php
$arrayIterator = new RecursiveArrayIterator([1, 2, 3, 4, 56, 7, 8, 'test' => [11, 22, 33, 44, 55]]);
$iterator = new RecursiveCachingIterator($arrayIterator, 256);
function recursiveCaching(RecursiveCachingIterator $iterator, $i = 0)
{
foreach ($iterator as $item) {
if ($iterator->hasChildren()) {
echo $iterator->key() . ' has children ' . PHP_EOL;
recursiveCaching($iterator->getChildren(), $i+1);
} else {
echo $iterator->key() . '.....' . $item . PHP_EOL;
}
if (!$iterator->hasNext()) {
echo $iterator->key() . ' is the end element' . PHP_EOL;
}
}
}
recursiveCaching($iterator);
//var_dump($iterator->getCache());
RecursiveCallbackFilterIterator 迭代器
RecursiveCallbackFilterIterator 迭代器 CallbackFilterIterator 并在此基础上实现了 OuterIterator 和 RecursiveIterator 接口。
<?php
class AnRecursiveCallbackFilterIterator extends RecursiveCallbackFilterIterator
{
public function accept()
{
return $this->current() >= 3;
}
}
function callback($value, $key, $iterator)
{
return $value >= 5;
}
$arrayIterator = new RecursiveArrayIterator([99, 2, 3, 4, 5, 6, 7, 'test' => [11, 22, 33, 44, 55, 66, 77]]);
$iterator = new AnRecursiveCallbackFilterIterator($arrayIterator, 'callback');
function recursiveCallback(RecursiveCallbackFilterIterator $iterator, $i = 0)
{
foreach ($iterator as $item) {
echo str_repeat("\t", $i);
if ($iterator->hasChildren()) {
echo $iterator->key() . ' has children ' . PHP_EOL;
recursiveCallback($iterator->getChildren(), $i+1);
} else {
echo $iterator->key() . '.....' . $item . PHP_EOL;
}
}
}
recursiveCallback($iterator);
RecursiveDirectoryIterator 迭代器
RecursiveDirectoryIterator 继承自 FilesystemIterator 并实现了 SeekableIterator 和 RecursiveIterator 接口,除了来自父类和实现接口的一些方法外他自身还提供了 getSubPath、getSubPathname 两个方法,他的迭代返回值为一个 splFileInfo 对象信息,这使得很容易的对目录进行迭代遍历。
<?php
$iterator = new RecursiveDirectoryIterator(__DIR__,RecursiveDirectoryIterator::SKIP_DOTS);
function recursiveDir(RecursiveDirectoryIterator $iterator, $i = 0)
{
foreach ($iterator as $item) {
if ($iterator->isDir()) {
recursiveDir(new RecursiveDirectoryIterator($iterator->getPathname(),RecursiveDirectoryIterator::SKIP_DOTS), $i + 1);
} else {
var_dump($item);
}
}
}
recursiveDir($iterator);
RecursiveFilterIterator 迭代器
RecursiveFilterIterator 迭代器是 FilterIterator 的子类并实现了 OuterIterator 和 RecursiveIterator 接口,使用它你可以对迭代对象的输出进行迭代过滤。
<?
php class AnRecursiveFilterIterator extends RecursiveFilterIterator
{
public function __construct(RecursiveIterator $iterator)
{
parent::__construct($iterator);
}
public function accept()
{
return $this->hasChildren() || strpos((string)$this->current(), '1') !== false;
}
}
$arrayIterator = new RecursiveArrayIterator([1, 2, 3, 4, 5, 6, 7, 8, 9, new RecursiveArrayIterator([11, 22, 33, 44, 55, 66])]);
$iterator = new AnRecursiveFilterIterator($arrayIterator);
function RecursiveFilter(RecursiveFilterIterator $iterator, $i = 0)
{
foreach ($iterator as $item) {
echo str_repeat("\t", $i);
if ($iterator->hasChildren()) {
echo $iterator->key() . ' has children' . PHP_EOL;
RecursiveFilter($iterator->getChildren(), $i + 1);
} else {
echo $iterator->current() . '.....' . $item . PHP_EOL;
}
}
}
RecursiveFilter($iterator);
RecursiveIteratorIterator 迭代器
RecursiveIteratorIterator 迭代器是 OuterIterator 迭代器的实现接口,使用它你可以对实现了 RecursiveIterator 的迭代器进行迭代。
<?php $arrayIterator = new RecursiveArrayIterator([1, 2, 3, 4, [1, 2, 3, 4, 5],
new RecursiveArrayIterator([12222, 333333, new RecursiveArrayIterator([1111, 2222, 3333, 4444])])]);
$iterator = new RecursiveIteratorIterator($arrayIterator);
function RecursiveIterator(RecursiveIteratorIterator $iterator)
{
foreach ($iterator as $item) {
echo str_repeat("\t", $iterator->getDepth());
echo $iterator->getDepth() . '....' . $item . PHP_EOL;
}
}
RecursiveIterator($iterator);
RecursiveRegexIterator 迭代器
RecursiveRegexIterator 是 RegexIterator 迭代器的子类,并在此基础上实现了 RecursiveIterator 迭代器接口,使得你可以对迭代的数据应用正则过滤。
<?php
$arrayIterator = new RecursiveArrayIterator([12, 3, 'abc123', 'bac213', [1122, 2233, 3344, 4455]]);
$iterator = new RecursiveRegexIterator($arrayIterator, '/^[123]/');
function RecursiveRegex(RecursiveRegexIterator $iterator)
{
foreach ($iterator as $item) {
if ($iterator->hasChildren()) {
RecursiveRegex($iterator->getChildren());
} else {
var_dump($item);
}
}
}
RecursiveRegex($iterator);
RecursiveTreeIterator 迭代器
RecursiveTreeIterator 迭代器是一个树形结构迭代器,使用它你可以很方便的遍历一个树形结构。
<?php
$arrayIterator = new RecursiveArrayIterator([1, 2, [3, 4, [5, 6, 7], 8], 9, 10]);
$iterator = new RecursiveTreeIterator($arrayIterator);
foreach ($iterator as $key => $value) {
echo $value . PHP_EOL;
}