PHP Conference Japan 2024

IteratorIterator 類別

(PHP 5 >= 5.1.0, PHP 7, PHP 8)

簡介

這個迭代器包裝器允許將任何 Traversable 的東西轉換成 Iterator。重要的是要理解,大多數沒有實現 Iterator 的類別都有其原因,因為它們很可能不允許完整的 Iterator 功能集。如果是這樣,應該提供技術來防止誤用,否則可能會發生例外或致命錯誤。

類別概要

class IteratorIterator implements OuterIterator {
/* 方法 */
public __construct(Traversable $iterator, ?string $class = null)
公開 current(): 混合
公開 key(): 混合
公開 next():
公開 rewind():
公開 valid(): 布林值
}

注意事項

注意:

這個類別允許透過 __call 魔術方法存取內部迭代器的方法。

目錄

新增註釋

使用者貢獻的註釋 4 則註釋

sven at rtbg dot de
9 年前
這個迭代器基本上只是另一個迭代器的包裝器。它沒有做任何花俏的事情,只是簡單地將 rewind()、next()、valid()、current() 和 key() 的任何呼叫轉發到內部迭代器。這個內部迭代器可以使用 getInnerIterator() 來取得。

一種特殊情況:當傳遞一個 IteratorAggregate 物件時,該物件的 getIterator() 方法將被呼叫,並且將會迭代該迭代器,並且在呼叫 getInnerIterator() 時也會返回它。

這個類別可以被繼承,因此它是您自定義類別的理想建構基礎,如果您只想修改一兩個迭代器方法,而不是全部。

想要修剪 current() 方法返回的字串嗎?

<?php

class TrimIterator extends IteratorIterator
{
public function
current() {
return
trim(parent::current());
}
}

$innerIterator = new ArrayIterator(array('normal', ' trimmable '));

$trim = new TrimIterator($innerIterator);

foreach (
$trim as $key => $value) {
echo
"Key:\n";
var_dump($key);
echo
"Value:\n";
var_dump($value);
echo
"---next---";
}
?>
輸出

鍵值
int(0)

string(6) "normal"
---next---鍵值
int(1)

string(9) "trimmable"
---next---
max-p at max-p dot me
8 年前
給任何想要盡可能模擬 foreach 行為以便使用一些挑剔的 Traversable 物件,而不使用 foreach 的人一點小提醒

- 在開始迭代之前,會呼叫 rewind()。
- 對於每次迭代,會在迭代器上呼叫以下方法
- valid()
- current()
- key()
- next()

這樣說聽起來很傻,但在我的使用案例中,我需要將 Traversable 資料庫結果游標轉換為程序式游標 (hasNext + fetchArray) 以實現向後相容性,並且驅動程式要求每個函式都按適當的順序呼叫。
thomas at gielfeldt dot dk
7 年前
IteratorIterator::current() 不會呼叫內部迭代器的 current() 方法。

內部迭代器的 current() 方法會在 rewind() 和 next() 上被呼叫(並快取)。key() 和 valid() 也是如此。

範例
<?php

$i
= new ArrayIterator(range(1,10));
$i = new IteratorIterator($i);
iterator_to_array($i); // 移動到結尾
print "有效: " . $i->valid() . "\n";
$i->append('test');
print
"有效: " . $i->valid() . "\n";
print
"目前: " . $i->current() . "\n";

?>
輸出

有效
有效
目前

然而
<?php

$i
= new ArrayIterator(range(1,10));
iterator_to_array($i); // 將迭代器轉換為陣列,這會使迭代器指向尾端
print "有效: " . $i->valid() . "\n";
$i->append('test');
print
"有效: " . $i->valid() . "\n";
print
"目前值: " . $i->current() . "\n";
?>

輸出

有效
有效: 1
目前值: test

原因如上所述,這是 `IteratorIterator` 呼叫 `current()`、`key()` 和 `valid()` 的方式所導致。
wallacemaxters at gmail dot lcom
8 年前
`IteratorIterator` 效率的另一個例子是一個用於迭代器列舉的小類別。

範例

<?php

class Enumerator extends IteratorIterator
{
/**
* 列舉器的初始值
* @param int
*/
protected $start = 0;

/**
* @param int
*/
protected $key = 0;

/**
* @param Traversable $iterator
* @param scalar $start
*/
public function __construct(Traversable $iterator, $start = 0)
{
parent::__construct($iterator);

$this->start = $start;

$this->key = $this->start;
}

public function
key()
{
return
$this->key;
}

public function
next()
{
++
$this->key;

parent::next();
}

public function
rewind()
{
$this->key = $this->start;

parent::rewind();
}

}
?>

這會產生

<?php

$enumerator
= new Enumerator(
new
ArrayIterator(['php', 'java', 'python']), 7000
);

print_r(iterator_to_array($enumerator));

/*
* array(3) {
7000 => 'php',
7001 => 'java',
7002 => 'python'
}
*/

?>
To Top