37

I'm trying to obtain the first key of an associative array, without creating a temporary variable via array_keys() or the like, to pass by reference. Unfortunately both reset() and array_shift() take the array argument by reference, so neither seem to be viable results.

With PHP 5.4 I'll be in heaven; array_keys($array)[0];, but unfortunately this of course is not an option either.

I could create a function to serve the purpose, but I can only imagine there is some concoction of PHP's array_* functions that will produce the desired result in a single statement, that I cannot think of or come up with.

So:

$array = array('foo' => 'bar', 'hello' => 'world');

$firstKey = assorted_functions($array); // $firstKey = 'foo'

The reason for the "no reference" clause in my question is only for the fact that I assume array_keys() will be required (if there is a way passing by reference, please fire away)

I'd use key(), but that requires a reset() as I'm not sure where the pointer will be at the time of this operation.


Addendum

I'm following up on a realization I had recently: as I mentioned in the comments, it'll use the memory all the same, so if that's a concern, this question hath no solution.

$a = range(0,99999);
var_dump(memory_get_peak_usage()); // int(8644416)
$k = array_keys($a)[0];
var_dump(memory_get_peak_usage()); // int(17168824)

I knew this, as PHP doesn't have such optimization capabilities, but figured it warranted explicit mention.

The brevity of the accepted answer is nice though, and'll work if you're working with reasonably sized arrays.

Dan Lugg
  • 20,192
  • 19
  • 110
  • 174
  • 1
    I've got a vague hackish idea of `foreach($array as &$key) { return $key; }` possibly accomplishing what you want, but I'm too lazy to test it, and not quite sure what you want. – Marc B Jul 14 '11 at 18:55
  • @Marc B foreach($array as $key=>$value) { return $key; } should work – RiaD Jul 14 '11 at 18:59
  • @Marc B - Trying for a single statement to return the value. I could wrap a `foreach` in a `call_user_func(function(){})` but that's a little crazy. – Dan Lugg Jul 14 '11 at 18:59
  • I just realized: I don't think it matters how you slice it because IIRC now, `array_keys()` creates a copy of the array keys in memory anyway, even with an immediate dereferencing. The single-expression brevity is nice, but the memory consumption still happens. – Dan Lugg Feb 05 '13 at 00:38
  • I just realized something else; this question has self-deprecated, as if you're still using <= 5.3, you've got problems. – Dan Lugg Apr 14 '14 at 05:05

5 Answers5

64

Although array_shift(array_keys($array)); will work, current(array_keys($array)); is faster as it doesn't advance the internal pointer.

Either one will work though.

Update

As @TomcatExodus noted, array_shift(); expects an array passed by reference, so the first example will issue an error. Best to stick with current();

adlawson
  • 6,303
  • 1
  • 35
  • 46
  • Bingo. Thank you much on `current(array_keys())`. Just for future reference, an array produced by `array_keys()` or `array_values()` is of course new, and therefore it's pointer is always at the first element, correct? – Dan Lugg Jul 14 '11 at 19:04
  • 1
    Excellent; Thanks again. I must need more coffee, because the more I look at the answer, the more glaringly obvious it seems :) Oh, and a note on `array_shift()`; it doesn't. PHP 5.3.6 with `error_reporting(-1)` issues an error. – Dan Lugg Jul 14 '11 at 19:06
  • 1
    is `key($array)` not faster? – Popnoodles Feb 21 '13 at 01:40
  • Maybe. It'll do the job. Use whatever you want. OP wanted something other than `key()` so this is it. – adlawson Mar 07 '13 at 13:06
  • current(array_keys($array)); is faster? or the following is faster foreach($array as $key => $val){ echo $key;break;} – Developer Oct 22 '14 at 10:43
  • @Developer I dunno. Test them and find out. If I'm honest though it doesn't really matter. Use whichever one you prefer. – adlawson Oct 23 '14 at 10:50
  • The problem in this question is how to return the first key. The answer below by @Brian Graham should be preferred because it: moves to the first key, and returns it. Nothing else. – Aaron Sep 29 '15 at 17:51
  • @Aaron I don't see why it's preferential to move the internal array pointer to the first just to return the value when you don't need to. It could in fact lead to unexpected behaviour if used inside control structures like a `while` loop. – adlawson Sep 30 '15 at 08:45
19

You can use reset and key:

reset( $array );
$first_key = key( $array );

or, you can use a function:

function firstIndex($a) { foreach ($a as $k => $v) return $k; }
$key = firstIndex( $array );
Nahydrin
  • 13,197
  • 12
  • 59
  • 101
1
array_shift(array_keys($array))
RiaD
  • 46,822
  • 11
  • 79
  • 123
1

each() still a temporary required, but potentially a much smaller overhead than using array_keys().

Orbling
  • 20,413
  • 3
  • 53
  • 64
  • Thanks @Orbling - True, there's a plethora of ways using a temporary, but that's what I'm trying to avoid. My struggle has gone from practical to academic :P – Dan Lugg Jul 14 '11 at 19:01
  • Also, perhaps should have mentioned; the array is not very long, just very deep. The first dimension will likely have 3 - 5 elements, so while `array_keys()` *is* more overhead, it's not producing an enormous array. – Dan Lugg Jul 14 '11 at 19:11
0

What about using array_slice (in combination with array_keys for associative arrays)?

$a = range(0,999999);
var_dump(memory_get_peak_usage());
$k = array_keys(array_slice($a, 0, 1, TRUE))[0];
var_dump(memory_get_peak_usage());
var_dump($k);
$k = array_keys($a)[0];
var_dump(memory_get_peak_usage());

Gives as output (at least with me):

int(36354360)
int(36355112)
int(0)
int(72006024)
int(0)
PrinsEdje80
  • 494
  • 4
  • 8