What is the proper way to use PHP iterators to implement identical functionality to the 'array_walk_recursive()' function?
我需要对所有数组元素进行递归迭代(即,对于遇到的本身就是数组的每个数组元素,我都需要迭代该数组)并在每个字符串(叶)值上执行trim()。 >
要使用与下面的链接中所述非常相似的示例,这是我需要的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <?php
// How to accomplish identical functionality using PHP iterators?
$sweet = array('a' => ' apple ', 'b' => ' banana ');
$fruits = array('sweet' => $sweet, 'sour' => ' lemon ');
function my_trim (&$item, $key)
{
// Trim the whitespace from the values
$item = trim($item);
}
array_walk_recursive($fruits, 'my_trim');
?> |
array_walk_recursive函数完全提供了我需要的功能。
但是,我想更好地理解PHP迭代器,并且通过使用迭代器实现与array_walk_recursive()函数相同的功能,我当前的任务似乎是一个很好的机会。
当我进入有关迭代器的PHP文档时,我看到了各种迭代器,但没有对其语义的整体描述。特别是,RecursiveArrayIterator似乎是显而易见的选择,如果不是针对RecursiveIteratorIterator类,并且此StackOverflow回答了类似的问题(它给出了代码,但没有使我满意地解释代码),我将尝试使用以前的迭代器(RecursiveArrayIterator),我什至可能都没有发布此问题。
但是,为了实际理解两个相关的迭代器类(RecursiveArrayIterator和RecursiveIteratorIterator)的文档,以便理解上面链接中的代码并满意使用(或不使用)-我在Google搜索中的任何地方都找不到关于这些迭代器语义的文档(特别是,如上所述,在官方的PHP文档中,我没有看到关于这些迭代器中任何一个的入门文档)。
因此,我想知道使用PHP迭代器实现与array_walk_recursive()函数相同的功能的正确方法是什么。 (大概,如果上面的SO链接上的代码正确,那么它将与链接的代码完全一样(或与之相似)-但我不仅要提供一个代码段,而且还要一个(简短的)说明。)
迭代器无意修改其内部元素。 Iterator用于在foreach循环中一个接一个地访问元素集合。
当然,您可以以返回修改后的字符串版本的方式覆盖Iterator的current()函数。但是,您仍然需要自己遍历所有元素以对其进行修改。
我将尝试通过示例进行说明:
1 2
| $sweet = array('a' => ' apple ', 'b' => ' banana ');
$fruits = array('sweet' => $sweet, 'sour' => ' lemon '); |
创建自定义的RecursiveIteratorIterator:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class CallbackRecursiveIteratorIterator extends
RecursiveIteratorIterator
{
public function __construct (RecursiveIterator $it, $callback) {
$this->callback = $callback;
parent ::__construct ($it);
}
public function current() {
return $this->callback->__invoke (parent ::current());
}
} |
创建该迭代器的实例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| $i = new CallbackRecursiveIteratorIterator (
new RecursiveArrayIterator (
$fruits
),
// pass callback here
function($element) {
return trim($element ." test");
}
);
// Iterate over modified values
foreach($i as $key => $el) {
var_dump($el);
} |
请注意,原始数组仍未更改:
我不知道使用RecursiveIteratorIterator修改原始数组的简单方法,相反,如您的示例所用的array_walk_recursive是更好的选择。
如果只想访问不修改原始数组的多维数组的叶子,则可以使用LEAVES_ONLY选项。
1 2 3 4 5 6 7 8 9
| $sweet = array('a' => ' apple ', 'b' => ' banana ');
$fruits = array('sweet' => $sweet, 'sour' => ' lemon ');
foreach (new RecursiveIteratorIterator (
new RecursiveArrayIterator ($fruits),
RecursiveIteratorIterator ::LEAVES_ONLY
) as $key => $value) {
print trim($value);
} |
请注意,在上面的foreach中,引用$ value即as $key => &$value是非法的,在这种情况下php将产生以下错误
1
| PHP Fatal error: An iterator cannot be used with foreach by reference |
RecursiveIteratorIterator递归地迭代实现Traversable(并扩展为Iterator)接口的任何递归对象。对于嵌套数组,您需要一个RecursiveArrayIterator迭代器对象
但是例如,您可能还具有RecursiveDirectoryIterator来遍历文件系统。
您遍历对象的路径可以由RecursiveIteratorIterator的第二个参数指定:
1 2 3
| RecursiveIteratorIterator::LEAVES_ONLY - The default. Lists only leaves in iteration.
RecursiveIteratorIterator::SELF_FIRST - Lists leaves and parents in iteration with parents coming first.
RecursiveIteratorIterator::CHILD_FIRST - Lists leaves and parents in iteration with leaves coming first. |