混合对象/数组迭代


Mixed object / array iteration

我需要一种方法来迭代任何数组或对象($this->_data)。

当前草案如下:

class values implements 'Iterator{
    private $_data = null; // array or object
    private $_keys = [];
    private $_key = false;
    // ------------ 'Iterator implementation
    public function current(){
        return $this->get($this->_key);
    }
    public function key(){
        return $this->_key;
    }
    public function next(){
        $this->_key = 'next($this->_keys);
    }
    public function rewind(){
        $this->_keys = [];
        foreach ($this->_data as $k => $v){
            $this->_keys[] = $k;
        }
        $this->_key = 'reset($this->_keys);
    }
    public function valid(){
        if (false === $this->_key){
            return false;
        }
        return $this->has($this->_key);
    }
}

问题是我不想为键保存额外的数组。

可能有一些更好的方法来迭代对象的键,避免为此目的创建额外的对象/数组?

(外部迭代器不是一个选项,因为我不希望在foreach循环中创建额外的对象)

混合使用本地myClass::方法和包装器的值::方法的例子

class myClass{
    var $x = 'x';
    var $y = 'y';
    public function hello(){
        echo 'Hello, '.$this->x;
    }
}
$a = new myClass();
$values = new values($a);
foreach ($values as $k => $v){
   $values[$k] = $v.' modified';
}
$a->hello();

其他说明:

  • values实例可以被重用(通过替换$this->_data)
  • 这个类的使用可以非常密集(从100到超过100000个不同的对象/数组传递)
  • 值可以在值包装器之外使用和/或更改(参见上面的例子)

虽然可以自己实现Iterator,但不需要单独存储$keys(如果需要,我可以显示),您可以使用或扩展ArrayObject类。它看起来很适合你的需要。

检查这个例子:

$a = new ArrayObject(array(
    'a' => 'foo',
    'b' => 'bar'
));
foreach($a as $k => $v) {
    var_dump($k, $v);
}
输出:

string(1) "a"
string(3) "foo"
string(1) "b"
string(3) "bar"

适用于PHP 5.5.0+

它实际上失败了,因为它会在每次调用

时创建Generator实例
class values implements IteratorAggregate{
    private $_data = null; // array or object
    public function __construct($data = null){
        $this->_data = $data;
    }
    private static function g($data){
        foreach ($data as $k => $v){
                yield $k => $v;
        }
    }
    public function getIterator(){
        return self::g($this->_data);
    }
}