19

I want to use an associative array with the PHP iterator:

http://php.net/manual/en/class.iterator.php

is it possible?

I defined these methods:

  public function rewind(){    
    reset($this->_arr);
    $this->_position = key($this->_arr);
  }

  public function current(){    
    return $this->_arr[$this->_position];
  }

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

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

  public function valid(){    
    return isset($this->_arr[$this->_position]);
  }

the problem is it doesn't iterate correctly. I only get one element.

I think it's because of the ++$this->_position code in the next() method which doesn't have any effect because _position is a string (key of the associative array).

so how can I go to the next element of this type of array?

4
  • 4
    Out of curiosity, why aren't you just using an ArrayIterator? Commented Jun 17, 2012 at 21:00
  • Can you please show more of your code? That would be a) the part where you say class XYZ implements Iterator b) the part where you (try to) use it. Commented Jun 17, 2012 at 21:03
  • 1
    "I defined these methods" -- it is called "copy-pasted as-is from documentation" ;-) Commented Jun 17, 2012 at 21:05
  • 4
    If this is for a class holding an array, consider implementing IteratorAggregate and return an ArrayIterator for that array in getIterator. Commented Jun 17, 2012 at 21:07

5 Answers 5

39
function rewind() {
    reset($this->_arr);
}

function current() {
    return current($this->_arr);
}

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

function next() {
    next($this->_arr);
}

function valid() {
    return key($this->_arr) !== null;
}
Sign up to request clarification or add additional context in comments.

3 Comments

In a foreach loop, I assume this won't return a key - only a numerical representation. Correct?
@OGHaza thanks. I think his latest edit seems ok to me? My orig code didn't have a bug, but I think I like his latest edit slightly better.
Excellent solution. Kindly also add count and other functions used in routine
5

Why not creating an ArrayObject from Your associative Array? Then You can getIterator() from this ArrayObject and call key(), next() etc on it as You want...

Some example:

$array = array('one' => 'ONE', 'two' => 'TWO', 'three' = 'THREE');
// create ArrayObject and get it's iterator
$ao = new ArrayObject($my_array);
$it = $ao->getIterator();
// looping
while($it->valid()) {
    echo "Under key {$it->key()} is value {$it->current()}";
    $it->next();
}

ArrayObject
ArrayIterator

Comments

2

http://ideone.com/Fxt0j

class myIterator implements Iterator {
    private $position = 0;
    private $keys;

    public function __construct(array $arr) {
        $this->array = $arr;
        $this->keys = array_keys($arr);
        $this->position = 0;
    }

    function rewind() {
        $this->position = 0;
    }

    function current() {
        return $this->array[$this->key()];
    }

    function key() {
        return $this->keys[$this->position];
    }

    function next() {
        ++$this->position;
    }

    function valid() {
        return isset($this->keys[$this->position]);
    }
}

$it = new myIterator(array(
        'a' => "firstelement",
        'b' => "secondelement",
        'c' => "lastelement",
    ));

foreach($it as $key => $value) {
    var_dump($key, $value);
    echo "\n";
}

9 Comments

This code would be even more useful if it was commented & explained, so others apart from the OP could benefit from your knowledge.
I really, really don't understand why to still reinvent the wheel... Using ArrayIterator got from ArrayObject that an associative array was turned into is much simpler... And no need to write down our own ArrayIterator...
This is just a copy of the php.net example
I came to this page from google after looking at the php.net example. The problem is taking credit for something that was not written by you. I would recomment mentioning the source, that way it is ok. The age of a comment is - IMO - irrelevant, useful info is always useful. If you don't want people commenting on your older posts, then, I don't know, delete it.
php.net/manual/en/class.iterator.php - Example #1 Basic usage. Sorry if I made you upset. Why you keep saying 2 years, is it that significant?
|
1
class MyItrator implements Iterator 
{
    private $_arr;

    public function __construct(array $arr) 
    {
        $this->_arr = $arr;
    }


    public function rewind()
    {
        reset($this->_arr);
    }

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

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

    public function next()
    {
        next($this->_arr);
    }

    public function valid()
    {
        return isset($this->_arr[key($this->_arr)]);
    }
}

Comments

0

I know this is an old question but it can be as simple as

public function current()
{
    return $this->array[array_keys($this->array)[$this->position]];
}

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

public function key()
{
    return array_keys($this->array)[$this->position];
}

public function valid()
{
    return array_key_exists($this->position, array_keys($this->array)[$this->position]);
}

public function rewind()
{
    $this->position = 0;
}

I know a similar answer was posted by @zerkms but imho that doesnt work if the object is already constructed and you have functionality that extends the array

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.