Iterator 是否仅适用于数值数组?
Does Iterator work only with numeric arrays?
我在 w3schools 看到了一个例子:
<?php
// Create an Iterator
class MyIterator implements Iterator {
private $items = [];
private $pointer = 0;
public function __construct($items) {
// array_values() makes sure that the keys are numbers
$this->items = array_values($items);
}
public function current() {
return $this->items[$this->pointer];
}
public function key() {
return $this->pointer;
}
public function next() {
$this->pointer++;
}
public function rewind() {
$this->pointer = 0;
}
public function valid() {
// count() indicates how many items are in the list
return $this->pointer < count($this->items);
}
}
// A function that uses iterables
function printIterable(iterable $myIterable) {
foreach($myIterable as $item) {
echo $item;
}
}
// Use the iterator as an iterable
$iterator = new MyIterator(["a", "b", "c"]);
printIterable($iterator);
?>
如果它是关联数组而不是关联数组,当前方法是否可以循环数组numeric.If是的,我该怎么做?例如,我们可以做这样的事情吗:
function printIterable(iterable $myIterable) {
foreach($myIterable as $item => $value) {
echo "$item - $value";
}
}
// Use the iterator as an iterable
$iterator = new MyIterator(["a"=>1, "b"=>2, "c"=>3]);
printIterable($iterator);
当我尝试的时候。它打印这个:0 - 11 - 22 - 3
PHP 以相同的方式处理数字和关联数组,打印它们时没有区别,并且相同的代码适用于两者(好吧,除非有人开始添加花哨的功能..)
是的,可以打印关联数组。
问题是您的代码通过将 $pointer 属性 初始化为 0(即数值)来假设数据数组键是数字。可以通过使用 PHP 数组 ($this->items) 的内部指针,或者保留数组键的显式列表来解决这个问题。
版本 1
PHP 具有遍历数组的函数,它们被命名为 next()、current()、key() 等,并列在 https://www.php.net/manual/en/ref.array.php 下。这样就可以在没有显式指针的情况下遍历数组:
while(key($arr) !== null) {
echo current($arr)."\n";
next($arr);
}
如果在 https://www.php.net/manual/en/class.iterator.php 下指定的方法在您的 class(implements Iterator
) 中实现,则可以使用这些函数,如下所示:
class MyIterator implements Iterator {
private $items = [];
private $pointer = 0;
public function __construct($items) {
$this->items = $items;
}
public function current() {
return current($this->items);
}
public function key() {
return key($this->items);
}
// ...
可以看出,它或多或少地输入了两次相同的调用。但是,如果您有一个更复杂的 Iterable 并且添加了其他代码片段,那么它可能开始变得值得工作了。
版本 2
如果您不想依赖版本 1 中的函数,您仍然可以使用 $this->pointer,但您必须保留数组键的显式列表:
class MyIterator implements Iterator {
private $items = [];
private $keys = [];
private $pointer = 0;
public function __construct($items) {
$this->items = array_values($items);
$this->keys = array_keys($items);
}
public function current() {
return $this->items[$this->keys[$this->pointer]];
// Alternative version:
return $this->items[$this->key()];
}
// Return the key of the current element
public function key() {
return $this->keys[$this->pointer];
}
// Step the array one element, and then return that value
public function next() {
// Check that we're not moving out of bounds, if so return null
// and follow the next() spec.
++$this->pointer;
return $this->items[$this->keys[$this->pointer]];
// Alternative version:
return $this->current();
}
// ...
正如所见,版本 2 创建了另一个数组“级别”来跟踪(如果关联数组和数字数组都应该被支持)。但是可以做到。
我在 w3schools 看到了一个例子:
<?php
// Create an Iterator
class MyIterator implements Iterator {
private $items = [];
private $pointer = 0;
public function __construct($items) {
// array_values() makes sure that the keys are numbers
$this->items = array_values($items);
}
public function current() {
return $this->items[$this->pointer];
}
public function key() {
return $this->pointer;
}
public function next() {
$this->pointer++;
}
public function rewind() {
$this->pointer = 0;
}
public function valid() {
// count() indicates how many items are in the list
return $this->pointer < count($this->items);
}
}
// A function that uses iterables
function printIterable(iterable $myIterable) {
foreach($myIterable as $item) {
echo $item;
}
}
// Use the iterator as an iterable
$iterator = new MyIterator(["a", "b", "c"]);
printIterable($iterator);
?>
如果它是关联数组而不是关联数组,当前方法是否可以循环数组numeric.If是的,我该怎么做?例如,我们可以做这样的事情吗:
function printIterable(iterable $myIterable) {
foreach($myIterable as $item => $value) {
echo "$item - $value";
}
}
// Use the iterator as an iterable
$iterator = new MyIterator(["a"=>1, "b"=>2, "c"=>3]);
printIterable($iterator);
当我尝试的时候。它打印这个:0 - 11 - 22 - 3
PHP 以相同的方式处理数字和关联数组,打印它们时没有区别,并且相同的代码适用于两者(好吧,除非有人开始添加花哨的功能..)
是的,可以打印关联数组。
问题是您的代码通过将 $pointer 属性 初始化为 0(即数值)来假设数据数组键是数字。可以通过使用 PHP 数组 ($this->items) 的内部指针,或者保留数组键的显式列表来解决这个问题。
版本 1 PHP 具有遍历数组的函数,它们被命名为 next()、current()、key() 等,并列在 https://www.php.net/manual/en/ref.array.php 下。这样就可以在没有显式指针的情况下遍历数组:
while(key($arr) !== null) {
echo current($arr)."\n";
next($arr);
}
如果在 https://www.php.net/manual/en/class.iterator.php 下指定的方法在您的 class(implements Iterator
) 中实现,则可以使用这些函数,如下所示:
class MyIterator implements Iterator {
private $items = [];
private $pointer = 0;
public function __construct($items) {
$this->items = $items;
}
public function current() {
return current($this->items);
}
public function key() {
return key($this->items);
}
// ...
可以看出,它或多或少地输入了两次相同的调用。但是,如果您有一个更复杂的 Iterable 并且添加了其他代码片段,那么它可能开始变得值得工作了。
版本 2 如果您不想依赖版本 1 中的函数,您仍然可以使用 $this->pointer,但您必须保留数组键的显式列表:
class MyIterator implements Iterator {
private $items = [];
private $keys = [];
private $pointer = 0;
public function __construct($items) {
$this->items = array_values($items);
$this->keys = array_keys($items);
}
public function current() {
return $this->items[$this->keys[$this->pointer]];
// Alternative version:
return $this->items[$this->key()];
}
// Return the key of the current element
public function key() {
return $this->keys[$this->pointer];
}
// Step the array one element, and then return that value
public function next() {
// Check that we're not moving out of bounds, if so return null
// and follow the next() spec.
++$this->pointer;
return $this->items[$this->keys[$this->pointer]];
// Alternative version:
return $this->current();
}
// ...
正如所见,版本 2 创建了另一个数组“级别”来跟踪(如果关联数组和数字数组都应该被支持)。但是可以做到。