RecursiveIteratorIterator 类

(PHP 5、PHP 7、PHP 8)

介绍

可用于遍历递归迭代器。

类概要

class RecursiveIteratorIterator implements OuterIterator {
/* 常量 */
public const int LEAVES_ONLY;
public const int SELF_FIRST;
public const int CHILD_FIRST;
public const int CATCH_GET_CHILD;
/* 方法 */
public __construct(Traversable $iterator, int $mode = RecursiveIteratorIterator::LEAVES_ONLY, int $flags = 0)
public current(): mixed
public endChildren(): void
public endIteration(): void
public getDepth(): int
public key(): mixed
public next(): void
public nextElement(): void
public rewind(): void
public setMaxDepth(int $maxDepth = -1): void
public valid(): bool
}

目录

添加注释

用户贡献的注释 7 个注释

匿名
7 年前
RecusiveIteratorIterator 与 RecursiveArrayIterator 结合使用的一个非常有用的用例是替换多维数组中任何深度的数组值。

通常,array_walk_recursive 将用于替换数组深处的值,但不幸的是,这仅在存在标准键值对时才有效——换句话说,array_walk_recursive 仅访问叶节点,而不是数组。

因此,为了解决这个问题,可以使用以下方式使用迭代器

<?php
$array
= [
'test' => 'value',
'level_one' => [
'level_two' => [
'level_three' => [
'replace_this_array' => [
'special_key' => 'replacement_value',
'key_one' => 'testing',
'key_two' => 'value',
'four' => 'another value'
]
],
'ordinary_key' => 'value'
]
]
];

$arrayIterator = new \RecursiveArrayIterator($array);
$recursiveIterator = new \RecursiveIteratorIterator($arrayIterator, \RecursiveIteratorIterator::SELF_FIRST);

foreach (
$recursiveIterator as $key => $value) {
if (
is_array($value) && array_key_exists('special_key', $value)) {
// 在这里,我们将所有键替换为来自'special_key'的相同值
$replaced = array_fill(0, count($value), $value['special_key']);
$value = array_combine(array_keys($value), $replaced);
// 设置一个新键
$value['new_key'] = 'new value';

// 获取当前深度并向上遍历树,保存修改
$currentDepth = $recursiveIterator->getDepth();
for (
$subDepth = $currentDepth; $subDepth >= 0; $subDepth--) {
// 获取当前层级迭代器
$subIterator = $recursiveIterator->getSubIterator($subDepth);
// 如果我们在想要更改的层级,使用替换值($value),否则将键设置为父迭代器的值
$subIterator->offsetSet($subIterator->key(), ($subDepth === $currentDepth ? $value : $recursiveIterator->getSubIterator(($subDepth+1))->getArrayCopy()));
}
}
}
return
$recursiveIterator->getArrayCopy();
// 返回:
$array = [
'test' => 'value',
'level_one' => [
'level_two' => [
'level_three' => [
'replace_this_array' => [
'special_key' => 'replacement_value',
'key_one' => 'replacement_value',
'key_two' => 'replacement_value',
'four' => 'replacement_value',
'new_key' => 'new value'
]
],
'ordinary_key' => 'value'
]
]
];
?>

关键在于向上遍历树以保存该层级的更改 - 仅仅调用 $recursiveIterator->offsetSet(); 将只在根数组上设置键。
Michiel Brandenburg
15 年前
您可以使用它来快速查找特定目录中的所有文件(递归)。这比自己维护一个堆栈要好。
<?php
$directory
= "/tmp/";
$fileSPLObjects = new RecursiveIteratorIterator(
new
RecursiveDirectoryIterator($directory),
RecursiveIteratorIterator::CHILD_FIRST
);
try {
foreach(
$fileSPLObjects as $fullFileName => $fileSPLObject ) {
print
$fullFileName . " " . $fileSPLObject->getFilename() . "\n";
}
}
catch (
UnexpectedValueException $e) {
printf("Directory [%s] contained a directory we can not recurse into", $directory);
}
?>
注意:如果搜索的目录中包含一个你没有读取权限的目录,将会抛出 UnexpectedValueException(导致你获得一个空列表)。
注意:返回的对象是 SPLFileObjects
Adil Baig @ AIdezigns
13 年前
关于 \RecursiveIteratorIterator 很重要的一点是,它在与 iterator_to_array 函数一起使用时会返回一个扁平化的数组。例如

<?php
$arr
= array('Zero', 'name'=>'Adil', 'address' => array( 'city'=>'Dubai', 'tel' => array('int' => 971, 'tel'=>12345487)), '' => 'nothing');

$iterator = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($arr));
var_dump(iterator_to_array($iterator,true));
?>

这段代码将返回

array(6) {
[0]=>
string(4) "Zero"
["name"]=>
string(4) "Adil"
["city"]=>
string(5) "Dubai"
["int"]=>
int(91)
["tel"]=>
int(12345487)
[""]=>
string(7) "nothing"
}

为了获得非扁平化的正确数组,使用 getArrayCopy() 方法,例如

$iterator->getArrayCopy()

这将返回

array(4) {
[0]=>
string(4) "Zero"
["name"]=>
string(4) "Adil"
["address"]=>
array(2) {
["city"]=>
string(5) "Dubai"
["tel"]=>
array(2) {
["int"]=>
int(91)
["tel"]=>
int(12345487)
}
}
[""]=>
string(7) "nothing"
}
aidan at php dot net
14 年前
此示例演示了如何在 RecursiveArrayIterator 中使用 getDepth() 方法。

<?php
$tree
= array();
$tree[1][2][3] = 'lemon';
$tree[1][4] = 'melon';
$tree[2][3] = 'orange';
$tree[2][5] = 'grape';
$tree[3] = 'pineapple';

print_r($tree);

$arrayiter = new RecursiveArrayIterator($tree);
$iteriter = new RecursiveIteratorIterator($arrayiter);

foreach (
$iteriter as $key => $value) {
$d = $iteriter->getDepth();
echo
"depth=$d k=$key v=$value\n";
}
?>

此代码的输出将是

Array
(
[1] => Array
(
[2] => Array
(
[3] => lemon
)

[4] => melon
)

[2] => Array
(
[3] => orange
[5] => grape
)

[3] => pineapple
)

depth=2 k=3 v=lemon
depth=1 k=4 v=melon
depth=1 k=3 v=orange
depth=1 k=5 v=grape
depth=0 k=3 v=pineapple
gerry at king-foo dot be
10 年前
使用 iterator_to_array() 时要小心。因为它会将你的子迭代器扁平化,具有相同键的元素会相互覆盖。

例如

<?php

$iterator
= new RecursiveIteratorIterator(
new
RecursiveArrayIterator([
[
'foo', 'bar'],
[
'baz', 'qux']
])
);

foreach (
$iterator as $element) {
echo
$element;
}

?>

这将按预期输出所有 4 个元素

string(3) "foo"
string(3) "bar"
string(3) "baz"
string(3) "qux"

而这样做

<?php

var_dump
(iterator_to_array($iterator));

?>

将输出一个只有最后 2 个元素的数组

array(2) {
[0]=>
string(3) "baz"
[1]=>
string(3) "qux"
}
Tom
13 年前
此类对元素树进行操作,该树通过将递归迭代器嵌套在一起而构建。

因此,你可以说它是一个迭代器,用于迭代迭代器。在遍历这些迭代器时,该类会在向下遍历到叶子时将迭代器推入堆栈,并在向上返回时从堆栈中移除它们。
fengdingbo at gmail dot com
10 年前
如果您想要遍历目录。
<?php
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator("./")) as $key=>$val)
{
echo
$key,"=>",$val,"\n";
}
?>
To Top