2

Consider a simple PHP ArrayObject with two items.

$ao = new ArrayObject();
$ao[] = 'a1';  // [0] => a1
$ao[] = 'a2';  // [1] => a2

Then delete the last item and add a new item.

$ao->offsetUnset(1);
$ao[] = 'a3';  // [2] => a3

I'd very much like to be able to have 'a3' be [1].

How can I reset the internal pointer value before I add 'a3'?

I have a simple function that does this but I'd rather not copy the array if I don't have to.

function array_collapse($array) {
    $return = array();
    while ($a = current($array)) {
        $return[] = $a;
        next($array);
    }
    return $return;
}
1
  • It occurs to me that my example is only one of a couple use-case scenarios that I'm encountering. For the sake of the question, I'll leave it intact but also add... If the array element(s) to be removed are not the last element(s) then a collapse is necessary before resetting the internal pointer. Is it possible to have an array of four elements ([0], [1], [2], and [3]), remove [1] and [2], and reset the pointer so the next element to be added gets [2]? Commented Sep 1, 2010 at 22:35

3 Answers 3

2

With the expansion on the question in your comments: you'd have to extend the ArrayObject class to get this kind of behavior:

class ReindexingArray extends ArrayObject {
    function offsetUnset($offset){
        parent::offsetUnset($offset);
        $this->exchangeArray(array_values($this->getArrayCopy()));
    }
    //repeat for every other function altering the values.
}

Another option would be the SplDoublyLinkedList:

<?php
$u = new SplDoublyLinkedList();
$array = array('1' => 'one',
               '2' => 'two',
               '3' => 'three');
foreach($array as $value) $u[] = $value;
var_dump($u);
unset($u[1]);        
var_dump($u);
$u[] = 'another thing';
var_dump($u);
Sign up to request clarification or add additional context in comments.

3 Comments

Is this still the best answer today? I have the same issue and I'm worried about the performance impact of the line $this->exchangeArray(array_values(...))
The best answer is to not care what number your keys are. Think about that first: why would you need what the OP needs?
well I had to loop over the members of the ArrayObject and delete some. To avoid this I went through the assumed keys from the highest to the lowest. But agreed: not needing to know the keys is the right solution, and I've already rewritten the code by using getArrayCopy()
0

Why not use offsetSet:

$ao = new ArrayObject();
$ao[] = 'a1';  // [0] => a1
$ao[] = 'a2';  // [1] => a2
$ao->offsetUnset(1);
$ao->offsetSet(1, 'a3');

1 Comment

Good point. My question missed a couple details that are very important. Thank you.
0

This is kind of lame, but you can cast it to standard array and use array_splice on it:

$ao = new ArrayObject();
$ao[] = 'element 1';
$ao[] = 'element 2';
$ao[] = 'element 3';
$ao[] = 'element 4';

var_dump($ao);

$items = (array) $ao;
array_splice($items, 1, 2);
$ao = new ArrayObject($items);
$ao[] = 'element 5';

var_dump($ao);

This results in:

object(ArrayObject)#1 (1) {
  ["storage":"ArrayObject":private]=>
  array(4) {
    [0]=>
    string(9) "element 1"
    [1]=>
    string(9) "element 2"
    [2]=>
    string(9) "element 3"
    [3]=>
    string(9) "element 4"
  }
}
object(ArrayObject)#2 (1) {
  ["storage":"ArrayObject":private]=>
  array(3) {
    [0]=>
    string(9) "element 1"
    [1]=>
    string(9) "element 4"
    [2]=>
    string(9) "element 5"
  }
}

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.