[英]RecursiveFilterIterator: how to not accept objects, but still visit their children?
I'm having difficulty to get RecursiveFilterIterator
to visit children of objects that I don't want to accept, without also returning the unacceptable object. 我很难让RecursiveFilterIterator
访问我不想接受的对象的子对象,而不返回不可接受的对象。
I have two types of Node
objects: NodeTypeA
and NodeTypeA
, that both extend abstract type Node
: 我有两种类型的Node
对象: NodeTypeA
和NodeTypeA
,它们都扩展了抽象类型Node
:
abstract class Node implements Countable, RecursiveIterator
{
protected $children;
public function __construct( array $children = array() )
{
$this->children = $children;
}
public function count()
{
return count( $this->children );
}
public function hasChildren()
{
if( !$this->valid() )
{
return false;
}
return count( $this->current() ) > 0;
}
public function getChildren()
{
return $this->current();
}
public function rewind()
{
reset( $this->children );
}
public function key()
{
return key( $this->children );
}
public function valid()
{
return null !== $this->key();
}
public function current()
{
return current( $this->children );
}
public function next()
{
next( $this->children );
}
}
class NodeTypeA extends Node {}
class NodeTypeB extends Node {}
... for which I defined this RecursiveFilterIterator
: ...我为此定义了这个RecursiveFilterIterator
:
class RecursiveNodeFilterIterator
extends RecursiveFilterIterator
{
public function __construct( RecursiveIterator $iterator, $kind )
{
parent::__construct( $iterator );
$this->kind = $kind;
}
public function accept()
{
$current = $this->current();
return $this->hasChildren() || $current instanceof $this->kind;
}
public function getChildren()
{
return new self( $this->getInnerIterator()->getChildren(), $this->kind );
}
}
Then, when I run this snippet: 然后,当我运行此代码段时:
header( 'Content-Type: text/plain; charset=utf-8' );
$nodes = new NodeTypeA( array(
new NodeTypeB( array(
new NodeTypeA( array(
new NodeTypeB( array(
new NodeTypeA(),
new NodeTypeA()
) ),
) ),
new NodeTypeA( array(
new NodeTypeB( array(
new NodeTypeB( array(
new NodeTypeA(),
new NodeTypeB()
) ),
) )
) ),
new NodeTypeB()
) ),
new NodeTypeA()
) );
$rii = new RecursiveIteratorIterator(
new RecursiveNodeFilterIterator( $nodes, 'NodeTypeA' ),
RecursiveIteratorIterator::SELF_FIRST
);
foreach( $rii as $node )
{
echo str_repeat( ' ', $rii->getDepth() ) . get_class( $node ) . PHP_EOL;
}
I was hoping to get this result: 我希望得到这个结果:
NodeTypeA
NodeTypeA
NodeTypeA
NodeTypeA
NodeTypeA
NodeTypeA
... but got: ......但得到了:
NodeTypeB
NodeTypeA
NodeTypeB
NodeTypeA
NodeTypeA
NodeTypeA
NodeTypeB
NodeTypeB
NodeTypeA
NodeTypeA
In other words, on iterating, it also returns NodeTypeB
objects when they have children. 换句话说,在迭代时,它还会在有子NodeTypeB
时返回NodeTypeB
对象。 This makes sense, since in RecursiveNodeFilterIterator::accept()
I have defined return $this->hasChildren() || ...
这是有道理的,因为在RecursiveNodeFilterIterator::accept()
我定义了return $this->hasChildren() || ...
return $this->hasChildren() || ...
, in order for the filter to visit all possible child nodes. return $this->hasChildren() || ...
,以便过滤器访问所有可能的子节点。
Is there a way to have RecursiveNodeFilterIterator
visit child nodes of NodeTypeB
without actually returning the NodeTypeB
nodes themselves? 有没有办法让RecursiveNodeFilterIterator
访问NodeTypeB
子节点而不实际返回NodeTypeB
节点本身?
A simple option is to wrap the RecursiveIteratorIterator
with a filter iterator that only accept
s the items that you are interested in. 一个简单的选择是使用过滤器迭代器包装RecursiveIteratorIterator
,该迭代器仅accept
您感兴趣的项目。
(Moved from comment to answer) (从评论转到回答)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.