25

Let S be an associative array in PHP, I need to retrieve and extract from it the first element, both the value and the key.

I would use

value1=array_pop(S);

but it only gives me the value.

I can use

K=array_keys(S);
key1=array_pop(K);
value1=array_pop(S);

but it is complicated because it requires to have two copies of the same data. WHich is a confusing since the array is itself an element in an array of arrays. There must be a more elegant way to just read the couple key/value while extracting it.

Pietro Speroni
  • 3,131
  • 11
  • 44
  • 55

5 Answers5

42
// first
$value = reset($arr);
$key = key($arr);

(in that order)

See reset()PHP Manual, key()PHP Manual.

unset($arr[$key]); # in case you want to remove it.

However array_pop()PHP Manual is working with the last element:

// last
$value = end($arr);
$key = key($arr);
unset($arr[$key]); # in case you want to remove it.

See end()PHP Manual.

For the fun:

[$value, $key] = [reset($arr), key($arr)]; // first
[$value, $key] = [end($arr), key($arr)]; // last

(PHP 7.1+)

or

list($value, $key) = array(reset($arr), key($arr)); // first
list($value, $key) = array(end($arr), key($arr)); // last

(PHP 4.3+)

or

extract(array('value' => reset($arr), 'key' => key($arr))); // first
extract(array('value' => end($arr), 'key' => key($arr))); // last

(PHP 4.3+; Caution: extract() in use!)

or

// first
reset($arr);
list($key, $value) = each($arr);


// last
end($arr);
list($key, $value) = each($arr);

(Note: The each() function is deprecated since PHP 7.2.0 and gone since PHP 8.0.0)

or whatever style of play you like ;)

Dealing with empty arrays

It was missing so far to deal with empty arrays. So it's a need to check if there is a last (first) element and if not, set the $key to null (as null can not be an array key):

// first
for ($key = null, $value = null; false !== $_ = reset($arr);)
{
    $value = $_;
    unset($arr[$key = key($arr)]);
    break;
}
unset($_);

// last
for ($key = null, $value = null; false !== $_ = end($arr);)
{
    $value = $_;
    unset($arr[$key = key($arr)]);
    break;
}
unset($_);

This will give for a filled array like $arr = array('first' => '1st', 'last' => '2nd.');:

string(4) "2nd." # value
string(4) "last" # key
array(1) { # leftover array
  ["first"]=>
  string(3) "1st"
}

And an empty array:

bool(false) # value
NULL # key
array(0) { # leftover array
}

Afraid of using unset?

In case you don't trust unset() having the performance you need (of which I don't think it's really an issue, albeit I haven't run any metrics), you can use the native array_pop() implementation as well (but I really think that unset() as a language construct might be even faster):

// first
reset($arr);
$key = key($arr);
$value = array_pop($arr);


// last
end($arr);
$key = key($arr);
$value = array_pop($arr);
hakre
  • 193,403
  • 52
  • 435
  • 836
  • Thanks. I am not convinced by: unset($arr[$key]); It looks like it would require the system to go through the array again to find the actual value. – Pietro Speroni Jul 07 '11 at 10:25
  • 2
    An array in PHP is a hash. That's a lookup operation not a search through the whole array and it is fast. – hakre Jul 07 '11 at 10:29
  • Yeah, I like it, too. In case you need to deal with empty arrays as well, it's getting a bit tricky for a compact form, so for the fun you find another edit. – hakre Jul 07 '11 at 10:55
  • Unfortunately I am testing it and it's not working. The prob is that I really need to delete the element, not just advance the counter. So I am afraid I will use to unset. Thanks for the help. :-) – Pietro Speroni Jul 07 '11 at 11:00
  • @Pietro: Afraid of using unset? I added another chunk of code, you can always opt for `array_shift` or `array_pop`. – hakre Jul 07 '11 at 12:34
  • This solution is for array_shift, *not* array_pop! Use `$value = end($arr);` and not ``$value = reset($arr);` to answer the question! – Alex Barker May 31 '17 at 00:58
  • @AlexBarker: Answer says that array_pop is working with the last element, this should highlight a potential confusion with the OP which has `array_pop()` in pseudo/example code but in wording a sentence like *"[...] I need to retrieve and extract from it the first element, both the value and the key."* - see as well [my original comment](https://stackoverflow.com/questions/6608934/popping-the-key-value-from-an-associative-array-in-php/6608968?noredirect=1#comment7800261_6608934) – hakre May 31 '17 at 01:47
7

array_slice

$arr = array('k1' => 'v1', 'k2' => 'v2', 'k3' => 'v3');

$a = array_slice($arr, 0, 1);
var_dump($a);

$arr = array_slice($arr, 1);
var_dump($arr);


array(1) {
  ["k1"]=>
  string(2) "v1"
}
array(2) {
  ["k2"]=>
  string(2) "v2"
  ["k3"]=>
  string(2) "v3"
}
OZ_
  • 12,492
  • 7
  • 50
  • 68
  • 1
    `array_slice()` is a nice idea. Depending in what should be done with the key and value: `list($key, $value) = array_slice($arr, 0, 1);` – KingCrunch Jul 07 '11 at 10:33
  • `array_slice()` is rather slow, isn't it? I mean it's a nice function but as far as popping from the end of the array is concerned... – hakre Jul 07 '11 at 10:41
  • array_slice with $preserve_keys set to true,will keep previous keys – shengbin_xu Sep 01 '20 at 01:15
6
$value = reset($array);
$key = key($array);

Edit: Hakre just beat me to it :-)

Sander Marechal
  • 22,978
  • 13
  • 65
  • 96
4
list($value, $key) = array(reset($s), key($s));
array_shift($s); // or just unset($s[$key]);

Of course you can split the first statement into two separate.

KingCrunch
  • 128,817
  • 21
  • 151
  • 173
  • what about: $key=key($s); $value=array_shift($s); Would that work? – Pietro Speroni Jul 07 '11 at 10:29
  • 1
    Yes. Thats what I meant with "you can split [it]" :) (as long as the array-pointer points to the first element (thats what `reset()` does), – KingCrunch Jul 07 '11 at 10:31
  • Unfortunately every time I use array_shift, the array comes out empty. Independently if I use a reset before. I think I'll use an unset, as suggested above. – Pietro Speroni Jul 07 '11 at 10:48
0

Here's what I did in a similar situation:

$last_index = count($test_array)-1;
if($last_index >= 0) {
    $last_key = array_keys($test_array)[$last_index];
    foreach($test_array as $k => $v) {
        if($k == $last_key)
            echo "last: ";
        echo $k . '=' . $v . PHP_EOL;
    }
}

although the solution I eventually ended up using was a while loop (I didn't really need to retain the keys).

I was basically trying to fit the elements of an array onto an area of a pdf by putting more than one on the same line. I used array_chunk() to break the array up into sub-arrays of 5-or-less each, then shifted the resultant array with a while(count($chunks) > 0) {}. Some of the solutions to this post could similarly shift/unset the elements of an array in a while loop until the array was empty.

Scott
  • 7,983
  • 2
  • 26
  • 41