817

What's the best way to determine the first key in a possibly associative array? My first thought it to just foreach the array and then immediately breaking it, like this:

foreach ($an_array as $key => $val) break;

Thus having $key contain the first key, but this seems inefficient. Does anyone have a better solution?

Blixt
  • 49,547
  • 13
  • 120
  • 153
Alex S
  • 25,241
  • 18
  • 52
  • 63
  • 4
    Why is inefficient foreach? – Emilio Gort Mar 17 '14 at 17:45
  • 2
    Compared to all the answers, foreach is still the fastest [FIDDLE, PHP 5.3](http://phpfiddle.org/lite/code/916y-x8m8), my localhost test on PHP 5.5 shows that the difference is slightly in favor of foreach. – Danijel Oct 31 '14 at 22:02
  • 3
    @Danijel, `foreach` is semantically wrong. – Pacerier Feb 17 '15 at 03:45
  • 2
    @AlexS, Either [`each($arr)['key']`](http://php.net/manual/en/function.each.php) or `each($arr)[0]` would work. – Pacerier Feb 17 '15 at 04:01
  • 1
    @Danijel Not any more... key: `0.0107`, foreach: `0.0217` – SeanJA Jul 30 '15 at 18:44
  • Note that if $an_array is empty, if you're lucky this solution gives "Undefined variable", or if you're not, it gives undefined results dependant on the existing value of $key. – ChrisJJ Dec 13 '15 at 17:27
  • 1
    `foreach` is still the most efficient way in php 7, but just like @Pacerier said, it is semantically wrong. Benchmark: `php -r '$n="\n";$m="microtime";$t=function($s,$e){$s=explode(" ",$s);$e=explode(" ",$e);return$e[1]-$s[1]+$e[0]-$s[0];};$a=[]; for($i=0;$i<100;++$i){$a["k".$i]=$i;}echo implode(", ",$a),$n;reset($a);echo"key(): ";$s=$m();for($i=0;$i<1e6;++$i){$k=key($a);}echo$k,$n,$t($s,$m()),$n; reset($a);echo"foreach: ";$s=$m();for($i=0;$i<1e6;++$i){foreach($a as$k=>$v){break;}}echo$k,$n,$t($s,$m()),$n;'` – Fishdrowned Jul 12 '16 at 05:27

25 Answers25

1424

2019 Update

Starting from PHP 7.3, there is a new built in function called array_key_first() which will retrieve the first key from the given array without resetting the internal pointer. Check out the documentation for more info.


You can use reset and key:

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

It's essentially the same as your initial code, but with a little less overhead, and it's more obvious what is happening.

Just remember to call reset, or you may get any of the keys in the array. You can also use end instead of reset to get the last key.

If you wanted the key to get the first value, reset actually returns it:

$first_value = reset($array);

There is one special case to watch out for though (so check the length of the array first):

$arr1 = array(false);
$arr2 = array();
var_dump(reset($arr1) === reset($arr2)); // bool(true)
Matt Kieran
  • 4,174
  • 1
  • 17
  • 17
Blixt
  • 49,547
  • 13
  • 120
  • 153
  • 150
    As a side note, `reset()` also happens to return the first element (value, not key) of any array, which can be handy as well. – devios1 Aug 21 '12 at 22:14
  • 6
    There's a comment in the docs to `reset()` saying `Don't use `reset()` to get the first value of an associative array. It works great for true arrays but works unexpectedly on Iterator objects. http://bugs.php.net/bug.php?id=38478` Is that still true? I'm confused – Dmitry Pashkevich Jan 23 '13 at 14:29
  • 15
    @DmitryPashkevich: Don't worry about that comment. They're not talking about `array` objects, but custom objects (that are not actual arrays). I guess they got the difference in data structures confused, but basically, `reset` returns the value of the first "key", which for objects would be `$prop` in the example given in the "bug" report, but for an array the first key. So don't worry, as long as you use real arrays (created with `array(…)`), you won't have a problem. – Blixt Jan 23 '13 at 17:55
  • Why is inefficient foreach as the op has in the question compare to all these answers? – Emilio Gort Mar 17 '14 at 17:49
  • 2
    It should be mentioned that end() and reset() have a side effect. However, most code in the world does not rely on the internal pointer being anywhere, so this is generally not a problem. – donquixote Mar 27 '14 at 01:11
  • Sorry, what if key() is called inside a function on an array passed as parameter to the function, should you use reset() before, or you can safely use key() directly? – tonix Nov 25 '14 at 16:20
  • 1
    @user3019105 There is only one internal pointer per array, which means that if any code outside your function changes it (by calling `next`, `reset`, `end` or looping through the array), you won't get the expected value when you call `key`. So yes, always call `reset` before using `key` to be sure you get what you want. – Blixt Dec 30 '14 at 16:00
  • @Blixt, Well, another way is to ensure code cleans itself up after it's done. So in this case we would be calling `reset` *after* calling `key` which works fine if enforced throughout the codebase. – Pacerier Feb 17 '15 at 03:49
  • @Pacerier True, and I'm not a fan of defensive programming either, but in this case I think the code can be made more robust and less dependent on the rest of the codebase by adding in the `reset` statement. The risk is that someone else uses a third-party library that unbeknownst to them calls `next` or something on the array which would break down the assumption that the array has been reset elsewhere. – Blixt Feb 17 '15 at 19:19
  • 1
    @Blixt, Yea, but we shouldn't be guarding against that. We've got to **understand** and trust the libraries we include into our system. They are assumed not to screw things up like calling `exit;` or forgetting to close things they open and whatnot. – Pacerier Feb 22 '15 at 21:10
  • `end` seems to cause an error in HHVM when using an "array-like" object (e.g. `ArrayObject`) instead of a PHP native array. – alexw Aug 15 '16 at 01:01
  • Does `reset()` mutate the source array as well? – jocull Aug 30 '16 at 16:46
  • 1
    @jocull `reset($a)` mutates the array `$a`'s internal key pointer, but not the values or keys themselves. – Blixt Aug 30 '16 at 16:54
86

array_keys returns an array of keys. Take the first entry. Alternatively, you could call reset on the array, and subsequently key. The latter approach is probably slightly faster (Thoug I didn't test it), but it has the side effect of resetting the internal pointer.

troelskn
  • 115,121
  • 27
  • 131
  • 155
  • 54
    Just a (late) note for future readers of this: The latter approach is not just "slightly" faster. There's a big difference between iterating an entire array, storing every key in another newly created array, and requesting the first key of an array as a string. – Blixt Sep 04 '09 at 06:33
  • 3
    Why is inefficient foreach as the op has in the question compare to all these answers? – Emilio Gort Mar 17 '14 at 17:46
  • 6
    @EmilioGort Good question. I don't think there's any difference in the performance of `foreach` + `break` and `reset` + `key` actually. But the former looks rather weird, so for stylistic issues, I would prefer the latter. – troelskn Mar 18 '14 at 14:05
  • @EmilioGort: Afaik, foreach() copies the array internally. So we can assume it to be slower. (Would be nice if someone could confirm that) – donquixote Mar 27 '14 at 01:10
  • 4
    @donquixote I don't know for sure, but assuming it's a regular array (and not an object implementing some kind or Iterator interface), I'm fairly sure `foreach` doesn't create an internal copy for it, but rather just iterates a pointer, similar to using the more low-level `next`, `current` etc. – troelskn Mar 27 '14 at 08:34
  • @troelskn Learned something today! http://nikic.github.io/2011/11/11/PHP-Internals-When-does-foreach-copy.html. I am a little puzzled by the "Referenced" example, but I think this has to do with the lazy copying of array arguments. Still, we would need a benchmark to compare foreach() and reset() + key(). – donquixote Mar 27 '14 at 16:19
  • Hmm.. this said, array_keys() is probably the expensive part! Unless PHP has yet another way to "cheat" and make this cheap.. – donquixote Mar 27 '14 at 17:11
  • `foreach` has the advantage that it's a more common use case now, so PHP engines would be more likely to optimize it compared to `key`. – Pacerier Feb 17 '15 at 03:51
55

Interestingly enough, the foreach loop is actually the most efficient way of doing this.

Since the OP specifically asked about efficiency, it should be pointed out that all the current answers are in fact much less efficient than a foreach.

I did a benchmark on this with php 5.4, and the reset/key pointer method (accepted answer) seems to be about 7 times slower than a foreach. Other approaches manipulating the entire array (array_keys, array_flip) are obviously even slower than that and become much worse when working with a large array.

Foreach is not inefficient at all, feel free to use it!

Edit 2015-03-03:

Benchmark scripts have been requested, I don't have the original ones but made some new tests instead. This time I found the foreach only about twice as fast as reset/key. I used a 100-key array and ran each method a million times to get some noticeable difference, here's code of the simple benchmark:

$array = [];
for($i=0; $i < 100; $i++)
    $array["key$i"] = $i;

for($i=0, $start = microtime(true); $i < 1000000; $i++) {
    foreach ($array as $firstKey => $firstValue) {
        break;
    }
}
echo "foreach to get first key and value: " . (microtime(true) - $start) . " seconds <br />";

for($i=0, $start = microtime(true); $i < 1000000; $i++) {
    $firstValue = reset($array);
    $firstKey = key($array);
}
echo "reset+key to get first key and value: " . (microtime(true) - $start) . " seconds <br />";

for($i=0, $start = microtime(true); $i < 1000000; $i++) {
    reset($array);
    $firstKey = key($array);
}
echo "reset+key to get first key: " . (microtime(true) - $start) . " seconds <br />";


for($i=0, $start = microtime(true); $i < 1000000; $i++) {
    $firstKey = array_keys($array)[0];
}
echo "array_keys to get first key: " . (microtime(true) - $start) . " seconds <br />";

On my php 5.5 this outputs:

foreach to get first key and value: 0.15501809120178 seconds 
reset+key to get first key and value: 0.29375791549683 seconds 
reset+key to get first key: 0.26421809196472 seconds 
array_keys to get first key: 10.059751987457 seconds

reset+key http://3v4l.org/b4DrN/perf#tabs
foreach http://3v4l.org/gRoGD/perf#tabs

Webmut
  • 2,559
  • 2
  • 17
  • 14
  • 3
    Do you have the benchmarks somewhere. Like how you tested etc. Anyway, thank you for running them! – flu Feb 06 '14 at 13:02
  • I would like to point at the fact, that there is same array used through the whole test. I think that this fact significantly influences the foreach approach. As @donquixote mentioned in comment to some response above - foreach internally copies the array. I can imagine that this copy is reused while running the benchmark since avoidance of array copying enhances performance only within this test. – Jarda Aug 11 '17 at 06:34
  • 2
    @Jarda As of php7, `foreach` never copies the array unless you directly modify it inside the foreach loop. On php5 the array structure could be copied in some cases (when its refcount > 1) and you are actually right it could be a significant influence there. Fortunately it's nothing to worry about on php7, where this issue was resolved. [Here](https://stackoverflow.com/questions/10057671/how-does-php-foreach-actually-work?noredirect=1&lq=1)'s a great read both on how foreach works under the hood now and how it worked in the past. – Webmut Aug 12 '17 at 02:18
  • 2
    as of php7.2 using the above benchmark, foreach is still fastest – But those new buttons though.. Jun 27 '18 at 16:47
39

key($an_array) will give you the first key

edit per Blixt: you should call reset($array); before key($an_array) to reset the pointer to the beginning of the array.

jimyi
  • 30,733
  • 3
  • 38
  • 34
  • 7
    Remember that the pointer of the array may not be at the first element, see my answer. – Blixt Jun 22 '09 at 18:17
  • I think this answer will help my case without reset because I'm first making sure the array has only one element. Thanks – groovenectar Sep 10 '14 at 14:49
37

You could try

array_keys($data)[0]
Pang
  • 9,564
  • 146
  • 81
  • 122
Stopper
  • 566
  • 4
  • 11
30

For 2018+

Starting with PHP 7.3, there is an array_key_first() function that achieve exactly this:

$array = ['foo' => 'lorem', 'bar' => 'ipsum'];
$firstKey = array_key_first($array); // 'foo'

Documentation is available here.

Code Slicer
  • 542
  • 6
  • 13
21
list($firstKey) = array_keys($yourArray);
Sergiy Sokolenko
  • 5,967
  • 35
  • 37
  • 3
    This is probably not the most efficient. – Yada May 12 '15 at 14:40
  • 3
    @Yada, yes, but this might be noticeable in rare cases; in most cases readability and maintainability are of much greater importance; and I also prefer solution which does not mutate original objects/arrays: e.g. reset($ar); $key = key($ar); -- is not always good idea, I'd rather chose MartyIX 's solution which is more concise than mine, e.g.: array_keys($ar)[0]; – Sergiy Sokolenko May 13 '15 at 08:55
21

If efficiency is not that important for you, you can use array_keys($yourArray)[0] in PHP 5.4 (and higher).

Examples:

# 1
$arr = ["my" => "test", "is" => "best"];    
echo array_keys($arr)[0] . "\r\n"; // prints "my"


# 2
$arr = ["test", "best"];
echo array_keys($arr)[0] . "\r\n"; // prints "0"

# 3
$arr = [1 => "test", 2 => "best"];
echo array_keys($arr)[0] . "\r\n"; // prints "1"

The advantage over solution:

list($firstKey) = array_keys($yourArray);

is that you can pass array_keys($arr)[0] as a function parameter (i.e. doSomething(array_keys($arr)[0], $otherParameter)).

HTH

MartyIX
  • 27,828
  • 29
  • 136
  • 207
15

Please find the following:

$yourArray = array('first_key'=> 'First', 2, 3, 4, 5);
$keys   =   array_keys($yourArray);
echo "Key = ".$keys[0];

Working Example:

Pupil
  • 23,834
  • 6
  • 44
  • 66
12
$myArray = array(
    2 => '3th element',
    4 => 'first element',
    1 => 'second element',
    3 => '4th element'
);
echo min(array_keys($myArray)); // return 1
Hamidreza
  • 1,825
  • 4
  • 29
  • 40
10

This could also be a solution:

$yourArray = array('first_key'=> 'First', 2, 3, 4, 5);
$first_key = current(array_flip($yourArray));
echo $first_key;

I have tested it and it works.

Working Code.

Arsen Khachaturyan
  • 7,904
  • 4
  • 42
  • 42
Pupil
  • 23,834
  • 6
  • 44
  • 66
5

To enhance on the solution of Webmut, I've added the following solution:

$firstKey = array_keys(array_slice($array, 0, 1, TRUE))[0];

The output for me on PHP 7.1 is:

foreach to get first key and value: 0.048566102981567 seconds 
reset+key to get first key and value: 0.11727809906006 seconds 
reset+key to get first key: 0.11707186698914 seconds 
array_keys to get first key: 0.53917098045349 seconds 
array_slice to get first key: 0.2494580745697 seconds 

If I do this for an array of size 10000, then the results become

foreach to get first key and value: 0.048488140106201 seconds 
reset+key to get first key and value: 0.12659382820129 seconds 
reset+key to get first key: 0.12248802185059 seconds 
array_slice to get first key: 0.25442600250244 seconds 

The array_keys method times out at 30 seconds (with only 1000 elements, the timing for the rest was about the same, but the array_keys method had about 7.5 seconds).

PrinsEdje80
  • 494
  • 4
  • 8
4
 $arr = array('key1'=>'value1','key2'=>'value2','key3'=>'key3');
 list($first_key) = each($arr);
 print $first_key;
 // key1
voodoo417
  • 11,861
  • 3
  • 36
  • 40
4

This is the easier way I had ever found. Fast and only two lines of code :-D

$keys = array_keys($array);
echo $array[$keys[0]];
Salvi Pascual
  • 1,788
  • 17
  • 22
3

The best way that worked for me was

array_shift(array_keys($array))

array_keys gets array of keys from initial array and then array_shift cuts from it first element value. You will need PHP 5.4+ for this.

Yuriy Petrovskiy
  • 7,888
  • 10
  • 30
  • 34
3

php73:

$array = ['a' => '..', 'b' => '..'];

array_key_first($array); // 'a'
array_key_last($array); // 'b';

http://php.net/manual/en/function.array-key-first.php

Benjamin Beganović
  • 1,070
  • 1
  • 8
  • 12
  • 1
    Including an explanation really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion – MichaelvE Dec 04 '18 at 01:14
2

Since PHP 7.3.0 function array_key_first() can be used.

There are several ways to provide this functionality for versions prior to PHP 7.3.0. It is possible to use array_keys(), but that may be rather inefficient. It is also possible to use reset() and key(), but that may change the internal array pointer. An efficient solution, which does not change the internal array pointer, written as polyfill:

<?php
if (!function_exists('array_key_first')) {
    function array_key_first(array $arr) {
        foreach($arr as $key => $unused) {
            return $key;
        }

        return null;
    }
}
?>
AndreyP
  • 2,510
  • 1
  • 29
  • 17
2

Re the @Blixt answer, prior to 7.3.0, this polyfill can be used:

if (!function_exists('array_key_first')) {
  function array_key_first(array $array) {
    return key(array_slice($array, 0, 1, true));
  }
}
Shahroq
  • 969
  • 1
  • 8
  • 15
1

This will work on all PHP versions

$firstKey = '' ;

//$contact7formlist - associative array. 

if(function_exists('array_key_first')){
    
    $firstKey = array_key_first($contact7formlist);
    
}else{
    
    foreach ($contact7formlist as $key => $contact7form ){
        $firstKey = $key;
        break;
    }
}
0

A one-liner:

$array = array('key1'=>'value1','key2'=>'value2','key3'=>'key3');
echo key( array_slice( $array, 0, 1, true ) );

# echos 'key1'
Kohjah Breese
  • 4,008
  • 6
  • 32
  • 48
0

Today I had to search for the first key of my array returned by a POST request. (And note the number for a form id etc)

Well, I've found this: Return first key of associative array in PHP

http://php.net/key

I've done this, and it work.

    $data = $request->request->all();
    dump($data);
    while ($test = current($data)) {
        dump($test);
        echo key($data).'<br />';die();
        break;
    }

Maybe it will eco 15min of an other guy. CYA.

Chris Stadler
  • 1,563
  • 1
  • 15
  • 17
0

I think the best and fastest way to do it is:

$first_key=key(array_slice($array, 0, 1, TRUE))
0

array_chunk split an array into chunks, you can use:

$arr = ['uno'=>'one','due'=>'two','tre'=>'three'];
$firstElement = array_chunk($arr,1,true)[0];
var_dump($firstElement);
Toto
  • 89,455
  • 62
  • 89
  • 125
Mauister
  • 1
  • 1
-1

You can play with your array

$daysArray = array('Monday', 'Tuesday', 'Sunday');
$day = current($transport); // $day = 'Monday';
$day = next($transport);    // $day = 'Tuesday';
$day = current($transport); // $day = 'Tuesday';
$day = prev($transport);    // $day = 'Monday';
$day = end($transport);     // $day = 'Sunday';
$day = current($transport); // $day = 'Sunday';

To get the first element of array you can use current and for last element you can use end

Edit

Just for the sake for not getting any more down votes for the answer you can convert you key to value using array_keys and use as shown above.

Priyank
  • 1,180
  • 1
  • 15
  • 26
-1

use :

$array = ['po','co','so'];

echo reset($array); 

Result : po

Javed Khan
  • 395
  • 5
  • 9