gre*_*emo 16 php arrays iterator traversal
这IteratorAggregate是一个创建外部迭代器的接口:
class myData implements IteratorAggregate
{
public $property1 = "Public property one";
public $property2 = "Public property two";
public $property3 = "Public property three";
public function __construct()
{
$this->property4 = "last property";
}
public function getIterator()
{
return new ArrayIterator($this);
}
}
$obj = new myData;
Run Code Online (Sandbox Code Playgroud)
并且您将能够使用foreach以下方式遍历对象:
foreach($obj as $key => $value) {
var_dump($key, $value);
echo "\n";
}
Run Code Online (Sandbox Code Playgroud)
虽然Iterator是外部迭代器或对象的接口,可以在内部迭代:
class myIterator implements Iterator
{
private $position = 0;
private $array = array('one', 'two', 'three');
function rewind()
{
$this->position = 0;
}
function current()
{
return $this->array[$this->position];
}
function key()
{
return $this->position;
}
function next()
{
++$this->position;
}
function valid()
{
return isset($this->array[$this->position]);
}
}
Run Code Online (Sandbox Code Playgroud)
而且,您可以基本上以相同的方式遍历它:
$it = new myIterator;
foreach($it as $key => $value) {
var_dump($key, $value);
echo "\n";
}
Run Code Online (Sandbox Code Playgroud)
所以任何人都可以解释为什么我们需要两个接口,它们之间有什么区别?
Ser*_*min 16
我假设IteratorAggregate您希望节省时间,Iterator适用于需要对对象进行迭代的精细控制的情况.例如,它可以让你添加自定义异常next(),key()或prev()返回他们之前的失败,高速缓存(如果通过的东西,在网络上获取数据迭代),预处理值.
tac*_*one 12
IteratorAggregate是一种实现迭代器的简单方法.缺点是你不能添加next(),key()等的方法,因为他们不会得到一个正常的过程叫foreach穿越.
如果需要实现自定义方法,则需要实现OuterIterator或(更容易)扩展IteratorIterator.
优点IteratorAggregate是速度,它比其他替代品快得多.它的问题是......尽管名称它不是迭代器而是可遍历(所以再次,没有下一个,关键,当前,有效,倒带方法).
这是一个简单的基准测试,我在我的笔记本电脑上运行,每一个都有100万次迭代IteratorAggregate,IteratorIterator并且OuterIterator都使用iterator_to_array和foreach:(
还要注意echo内部聚合的next方法:没有'x'被打印,证明它永远不会被调用)
$ repeat 3 php benchIterator.php
------------------------------------
Outer_ToArray: 569.61703300476 ms
Aggregate_ToArray: 552.38103866577 ms
IteratorIt_ToArray: 546.95200920105 ms
Outer_Foreach: 1679.8989772797 ms
IteratorIt_Foreach: 1019.6850299835 ms
Aggregate_Foreach: 367.35391616821 ms
------------------------------------
Outer_ToArray: 570.75309753418 ms
Aggregate_ToArray: 544.40784454346 ms
IteratorIt_ToArray: 555.06300926208 ms
Outer_Foreach: 1682.2130680084 ms
IteratorIt_Foreach: 988.21592330933 ms
Aggregate_Foreach: 356.41598701477 ms
------------------------------------
Outer_ToArray: 566.06101989746 ms
Aggregate_ToArray: 543.1981086731 ms
IteratorIt_ToArray: 546.28610610962 ms
Outer_Foreach: 1663.2289886475 ms
IteratorIt_Foreach: 995.28503417969 ms
Aggregate_Foreach: 356.16087913513 ms
Run Code Online (Sandbox Code Playgroud)
这是我用于基准测试的代码:
<?php
class Aggregate implements \IteratorAggregate
{
protected $var;
public function __construct($var = null)
{
if (is_array($var)) {
$this->var = new ArrayIterator($var);
}
if ($var instanceof \Traversable) {
$this->var = $var;
}
}
public function next()
{
echo 'x';
}
public function toArray()
{
return iterator_to_array($this->var, true);
}
public function getIterator()
{
return $this->var;
}
}
class Outer implements \OuterIterator
{
protected $var;
public function __construct($var = null)
{
if (is_array($var)) {
$this->var = new ArrayIterator($var);
}
if ($var instanceof \Traversable) {
$this->var = $var;
}
}
public function toArray()
{
return iterator_to_array($this->var, true);
}
public function getInnerIterator()
{
return $this->var;
}
public function current()
{
return $this->var->current();
}
public function next()
{
$this->var->next();
}
public function key()
{
return $this->var->key();
}
public function valid()
{
return $this->var->valid();
}
public function rewind()
{
$this->var->rewind();
}
}
class IteratorIt extends IteratorIterator
{
public function __construct($var = null)
{
if (is_array($var)) {
$var = new ArrayIterator($var);
}
parent::__construct($var);
}
public function toArray()
{
return iterator_to_array($this->getInnerIterator(), true);
}
public function getIterator()
{
return $this->getInnerIterator();
}
}
function bench($name, $test)
{
echo "$name: ";
$start = microtime(true);
$test();
$time = microtime(true);
$time -= $start;
echo ($time * 1000) . ' ms' . PHP_EOL;
}
$max = 1e6;
$array = range (1, 1e6);
$testSuites = [
'Outer_ToArray' => function () use ($max, $array) {
$iterator = new Outer($array);
$r = $iterator->toArray();
},
'Aggregate_ToArray' => function () use ($max, $array) {
$iterator = new Aggregate($array);
$r = $iterator->toArray();
},
'IteratorIt_ToArray' => function () use ($max, $array) {
$iterator = new IteratorIt($array);
$r = $iterator->toArray();
},
'Outer_Foreach' => function () use ($max, $array) {
$iterator = new Outer($array);
foreach ($iterator as $k => $v)
{
}
},
'IteratorIt_Foreach' => function () use ($max, $array) {
$iterator = new IteratorIt($array);
foreach ($iterator as $k => $v)
{
}
},
'Aggregate_Foreach' => function () use ($max, $array) {
$iterator = new Aggregate($array);
foreach ($iterator as $k => $v)
{
}
},
];
echo '------------------------------------'.PHP_EOL;
foreach ($testSuites as $name => $test) {
bench($name, $test);
}
Run Code Online (Sandbox Code Playgroud)
他们之间有什么区别?
名称的差异("聚合").
Aggregate是什么意思?
聚合状态通过禁止外部对象保持对其成员的引用来保证聚合内所做更改的一致性. (维基百科)
TC代码:
class myData implements IteratorAggregate {//your implementation}
class myIterator implements Iterator {//your implementation}
Run Code Online (Sandbox Code Playgroud)
以下是聚合清晰度的代码:
$renderFunction = function($iterator) {
foreach($iterator as $key => $value) {
echo "$key: $value\n";
foreach($iterator as $key => $value) {
echo " $key: $value\n";
}
}
};
$renderFunction(new myData); // Aggregate on
$renderFunction(new myIterator); // Aggregate off
Run Code Online (Sandbox Code Playgroud)
你对案件的期望是什么?
property1: Public property one
property1: Public property one
property2: Public property two
property3: Public property three
property4: last property
property2: Public property two
property1: Public property one
property2: Public property two
property3: Public property three
property4: last property
property3: Public property three
property1: Public property one
property2: Public property two
property3: Public property three
property4: last property
property4: last property
property1: Public property one
property2: Public property two
property3: Public property three
property4: last property
Run Code Online (Sandbox Code Playgroud)
VS
0: one
0: one
1: two
2: three
Run Code Online (Sandbox Code Playgroud)
通过实施IteratorAggregate,我们委托实施迭代器功能(的工作key(),next(),current(),valid(),rewind())到其他类(只实现getIterator().
这样,它可以帮助我们在OOP中实现单独的关注点.