PHP Conference Japan 2024

RecursiveIteratorIterator 類別

(PHP 5, PHP 7, PHP 8)

簡介

可用於迭代遞迴迭代器。

類別概要

class RecursiveIteratorIterator implements OuterIterator {
/* 常數 */
public const int LEAVES_ONLY;
公開 常數 整數 SELF_FIRST;
公開 常數 整數 CHILD_FIRST;
公開 常數 整數 CATCH_GET_CHILD;
/* 方法 */
公開 __construct(可遍歷 $iterator, 整數 $mode = RecursiveIteratorIterator::LEAVES_ONLY, 整數 $flags = 0)
公開 beginChildren():
公開 current(): 混合
公開 endChildren():
公開 endIteration():
公開 getDepth(): 整數
公開 key(): 混合
公開 next():
公開 nextElement():
公開 rewind(): void
公開 setMaxDepth(int $maxDepth = -1): void
公開 valid(): bool
}

目錄

新增註解

使用者提供的註解 7 則註解

匿名
8 年前
RecursiveIteratorIterator 與 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)) {
// Here we replace ALL keys with the same value from 'special_key'
$replaced = array_fill(0, count($value), $value['special_key']);
$value = array_combine(array_keys($value), $replaced);
// set a new key
$value['new_key'] = 'new value';

// Get the current depth and traverse back up the tree, saving the modifications
$currentDepth = $recursiveIterator->getDepth();
for (
$subDepth = $currentDepth; $subDepth >= 0; $subDepth--) {
// Get the current level iterator
$subIterator = $recursiveIterator->getSubIterator($subDepth);
// If we are on the level we want to change, use the replacements ($value) other wise set the key to the parent iterators value
$subIterator->offsetSet($subIterator->key(), ($subDepth === $currentDepth ? $value : $recursiveIterator->getSubIterator(($subDepth+1))->getArrayCopy()));
}
}
}
return
$recursiveIterator->getArrayCopy();
// return:
$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("目錄 [%s] 包含一個我們無法遞迴進入的目錄", $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";
}
?>

此程式碼的輸出結果為

陣列
(
[1] => 陣列
(
[2] => 陣列
(
[3] => lemon
)

[4] => melon
)

[2] => 陣列
(
[3] => orange
[5] => grape
)

[3] => pineapple
)

深度=2 k=3 v=lemon
深度=1 k=4 v=melon
深度=1 k=3 v=orange
深度=1 k=5 v=grape
深度=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));

?>

只會輸出包含最後兩個元素的陣列

array(2) {
[0]=>
string(3) "baz"
[1]=>
string(3) "qux"
}
Tom
13 年前
這個類別操作一個元素樹,它是由巢狀遞迴迭代器彼此嵌套所建構的。

因此,您可以說它是迭代器之上的迭代器。在遍歷這些迭代器時,該類別會在向下遍歷到葉節點時將迭代器推送到堆疊中,並在返回時將它們從堆疊中移除。
fengdingbo at gmail dot com
11 年前
如果您想遍歷目錄。
<?php
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator("./")) as $key=>$val)
{
echo
$key,"=>",$val,"\n";
}
?>
To Top