14

Is it possible to set PHP's internal array pointer without first iterating through the array. Take the following dummy code as example:

$array = range(1, 100);

// Represents the array key
$pointer = 66;

set_array_pointer($pointer, $array);

$nextValue = next($array); // Should return 68
10
  • 4
    $pointer is meant to hold the key or the value? Personally I don't think there's a PHP way of making the array pointer jump to a location and some sort of looping will be involved. Commented Apr 19, 2016 at 13:04
  • 3
    @apokryfos Thanks for pointing that out to me :) Commented Apr 19, 2016 at 13:07
  • 1
    Basically all those functions (next/prev/current/key) only really make sense when you are doing some kind of looping over that data anyway … Commented Apr 19, 2016 at 13:55
  • 1
    Some tips here: sitepoint.com/community/t/… Commented Apr 19, 2016 at 14:03
  • 1
    does your intellectual curiosity only concern loops in userland or also the internal handling of php? The answer by LibertyPaul has a way of setting the pointer without you triggering a loop in userland, but php will internally loop through the array when calling $iterator->seek() (at least as my limited c knowledge tells me here: github.com/php/php-src/blob/master/ext/spl/spl_array.c#L1347) Commented Apr 22, 2016 at 12:38

4 Answers 4

11

You can do this with ArrayObject and ArrayIterator:

$array = range(1, 100);
$pointer = 66;

$arrayobject = new ArrayObject($array);
$iterator = $arrayobject->getIterator();
$iterator->seek($pointer);     //set position
$iterator->next();             // move iterator
$nextValue = $iterator->current();
Sign up to request clarification or add additional context in comments.

Comments

10
+50

The solution LibertyPaul provided using ArrayIterator::seek seems to be the only way to make php set a pointer to a position within an array without initializing looping in userland. php will internally loop through the array to set the pointer, though, as you can read from the php source of ArrayIterator::seek():

/* {{{ proto void ArrayIterator::seek(int $position)
   Seek to position. */
SPL_METHOD(Array, seek)
{
    zend_long opos, position;
    zval *object = getThis();
    spl_array_object *intern = Z_SPLARRAY_P(object);
    HashTable *aht = spl_array_get_hash_table(intern);
    int result;

    if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &position) == FAILURE) {
        return;
    }

    if (!aht) {
        php_error_docref(NULL, E_NOTICE, "Array was modified outside object and is no longer an array");
        return;
    }

    opos = position;

    if (position >= 0) { /* negative values are not supported */
        spl_array_rewind(intern);
        result = SUCCESS;

        while (position-- > 0 && (result = spl_array_next(intern)) == SUCCESS);

        if (result == SUCCESS && zend_hash_has_more_elements_ex(aht, spl_array_get_pos_ptr(aht, intern)) == SUCCESS) {
            return; /* ok */
        }
    }
    zend_throw_exception_ex(spl_ce_OutOfBoundsException, 0, "Seek position %pd is out of range", opos);
} /* }}} */

So it looks like there is no way to set an array-pointer to a certain position without looping through the array

1 Comment

So it seems that the best answer, however disapointing is no. Thank you.
3

you can define your own function using next() and reset() to use pointer and use like below code

<?php
function findnext (&$array,$key) { 
   reset ($array); 
   while (key($array) !== $key) { 
     if (next($array) === false) throw new Exception('can not find key'); 
   } 
} 

$array = range(1, 100);
$pointer = 66;

findnext($array,$pointer); 
echo next($array); //this will give 68
?>

Comments

0

You don't need to set actual pointer for array. php already has support for internal array pointers see next() method:

$transport = array('foot', 'bike', 'car', 'plane');
$mode = current($transport); // $mode = 'foot';
$mode = next($transport);    // $mode = 'bike';
$mode = next($transport);    // $mode = 'car';
$mode = prev($transport);    // $mode = 'bike';
$mode = end($transport);     // $mode = 'plane';

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.