获取(可能)关联数组中的第一个键?


756

在可能的关联数组中确定第一个键的最佳方法是什么?我首先想到的是,它只存储数组,然后立即破坏它,如下所示:

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

因此,让$ key包含第一个键,但这似乎效率很低。有谁有更好的解决方案?


4
为什么效率低下的foreach?
Emilio Gort

2
与所有答案相比,foreach仍然是最快的FIDDLE,PHP 5.3,我在PHP 5.5上进行的localhost测试表明,差异稍微偏向于foreach。
Danijel 2014年

3
@Danijel foreach在语义上是错误的。
Pacerier

2
@AlexS,each($arr)['key']或者each($arr)[0]可以使用。
和平者

1
@Danijel没有更多...键:0.0107,foreach:0.0217
SeanJA

Answers:


1337

2019更新

PHP 7.3开始,有一个名为的新内置函数array_key_first(),它将在不重置内部指针的情况下从给定数组检索第一个键。查看文档以获取更多信息。


您可以使用resetkey

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

它本质上与您的初始代码相同,但是开销更少,而且发生的事情更加明显。

请记住要调用reset,否则您可能会得到数组中的任何键。您也可以使用end而不是reset获取最后一个密钥。

如果您希望键获取第一个值,则reset实际上返回它:

$first_value = reset($array);

不过,有一种特殊情况需要提防(因此请先检查数组的长度):

$arr1 = array(false);
$arr2 = array();
var_dump(reset($arr1) === reset($arr2)); // bool(true)

141
附带说明一下,reset()也可能会返回任何数组的第一个元素(值,而不是键),这也很方便。
devios1 2012年

5
在文档中有一条评论reset()Don't use reset()以获得关联数组的第一个值。它适用于真正的数组,但是在Iterator对象上却无法正常工作。bugs.php.net/bug.php ? id=38478`还是这样吗?我很困惑
Dmitry Pashkevich 2013年

13
@DmitryPashkevich:不用担心这个评论。他们不是在谈论array对象,而是在谈论自定义对象(不是实际的数组)。我猜他们混淆了数据结构的区别,但是从根本上说,它reset返回第一个“键”的值,对于对象,这将$prop在“错误”报告中给出的示例中,而对于数组,则是第一个键。因此,请放心,只要您使用实数组(由创建array(…)),就不会有问题。
Blixt

2
应该提到的是end()和reset()有副作用。但是,世界上大多数代码都不依赖于内部指针在任何地方,因此这通常不是问题。
donquixote 2014年

1
@ user3019105只有一个每个阵列内部指针,这意味着,如果你的函数之外的任何代码改变它(通过调用nextresetend或通过数组循环),你会不会当你调用得到的预期值key。因此,是的,请始终reset在使用之前致电key以确保您获得所需的东西。
Blixt 2014年

80

array_keys返回键数组。以第一个条目。或者,您可以调用reset数组,然后调用key。后一种方法可能会稍微快一些(我没有测试过),但是它具有重置内部指针的副作用。


52
只是为以后的读者提供的(最后)注释:后一种方法不仅“稍微”更快。在迭代整个数组,将每个键存储在另一个新创建的数组中以及将数组的第一个键请求为字符串之间有很大的区别。
Blixt

3
为什么像问题中的op那样效率低下的foreach与所有这些答案相比?
Emilio Gort 2014年

5
@EmilioGort好问题。我认为foreach+ breakreset+ 的性能key实际上没有任何区别。但是前者看起来很奇怪,因此对于样式问题,我更喜欢后者。
troelskn 2014年

@EmilioGort:Afaik,foreach()在内部复制数组。因此,我们可以假设它速度较慢。(如果有人可以确认,那就太好了)
donquixote 2014年

3
@donquixote我不确定,但是假设它是一个常规数组(而不是实现某种种类或Iterator接口的对象),我很确定foreach不会为其创建内部副本,而只是迭代一个指针,类似于使用更底层的工具nextcurrent等等
troelskn 2014年

54

有趣的是,foreach循环实际上是最有效的方法。

由于OP特别询问了效率,因此应该指出,当前所有答案的效率实际上都比foreach低得多。

我使用php 5.4进行了基准测试,并且reset / key指针方法(可接受的答案)似乎比foreach慢7倍。操纵整个阵列的其他方法(array_keys,array_flip)明显更慢比,并成为用大阵工作时更糟糕。

Foreach一点也不低效,请随时使用它!

编辑2015-03-03:

基准脚本已被要求,我没有原始脚本,但是做了一些新的测试。这次,我发现foreach仅是reset / key的两倍。我使用了100个键的数组,并且每种方法都运行了100万次,以得到一些明显的不同,这是简单基准测试的代码:

$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 />";

在我的PHP 5.5上,输出:

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

重置+键http://3v4l.org/b4DrN/perf#tabs for
每个http://3v4l.org/gRoGD/perf#tabs


3
您是否有基准测试。就像您测试的方式一样。无论如何,感谢您运行它们!
2014年

我想指出一个事实,整个测试中使用的数组相同。我认为,这一事实极大地影响了foreach方法。正如@donquixote在上面对某些响应的评论中提到的那样-foreach在内部复制数组。我可以想象在运行基准测试时可以重复使用此副本,因为避免数组复制只会在此测试中提高性能。
亚尔达(Jarda)

2
@Jarda从php7开始,foreach除非直接在foreach循环内修改数组,否则切勿复制该数组。在php5上,可以在某些情况下复制数组结构(当其refcount> 1时),实际上您是对的,这可能会对那里产生重大影响。幸运的是,在此问题已解决的php7上,无需担心。是一本很棒的书,既介绍了foreach现在如何工作以及过去如何工作。
Webmut

2
截至使用上述基准的php7.2,foreach仍是最快的
-billynoah

36

key($an_array) 会给你第一把钥匙

每个Blixt编辑:您应该在调用reset($array);之前key($an_array)将指针重置为数组的开头。


7
请记住,数组的指针可能不在第一个元素上,请参阅我的答案。
Blixt

我认为此答案将对我的情况有所帮助,而无需重置,因为我首先确保数组只有一个元素。谢谢
groovenectar 2014年


22



从PHP 7.3开始的2018+版本中,有一个array_key_first()函数可以完全实现此目的:

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

文档可在此处获得。😉


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

2
这可能不是最有效的。
亚达

3
@Yada,是的,但是在极少数情况下这可能会很明显;在大多数情况下,可读性和可维护性更为重要;我也更喜欢不变异原始对象/数组的解决方案:例如reset($ ar); $ key =键($ ar); -并非总是一个好主意,我宁愿选择比我更简洁的MartyIX解决方案,例如:array_keys($ ar)[0];
瑟吉·索科连科

20

如果效率对您而言并不那么重要,则可以array_keys($yourArray)[0]在PHP 5.4(及更高版本)中使用。

例子:

# 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"

解决方案的优势:

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

是您可以将其array_keys($arr)[0]作为函数参数(即doSomething(array_keys($arr)[0], $otherParameter))传递。

高温超导


3
确实array_keys($arr)[0]语法是有效的?
trante

5
它在PHP 5.4中。叫做array dereferencing。例如见:schlueters.de/blog/archives/...
马丁Vseticka

@trante,除PHP <5.4外,它在阳光下的所有语言中均有效。
Pacerier

13

请找到以下内容:

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

工作示例:


12
$myArray = array(
    2 => '3th element',
    4 => 'first element',
    1 => 'second element',
    3 => '4th element'
);
echo min(array_keys($myArray)); // return 1

1
@jurgemaister max()不会返回assoc数组的第一个键。列表或数组项的最大返回最大值
Hamidreza 2012年

5
不是OP请求,但在某些情况下非常有用。
d.raev

9

这也可以是一个解决方案:

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

我已经对其进行了测试,并且可以正常工作。

工作守则


3
array_flip():只能翻转STRING和INTEGER值!
2013年

5

为了增强Webmut的解决方案,我添加了以下解决方案:

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

我在PHP 7.1上的输出是:

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 

如果我对大小为10000的数组执行此操作,则结果将变为

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 

array_keys方法在30秒后超时(只有1000个元素,其余时间大约相同,但是array_keys方法大约为7.5秒)。


3
 $arr = array('key1'=>'value1','key2'=>'value2','key3'=>'key3');
 list($first_key) = each($arr);
 print $first_key;
 // key1




0

单线:

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

# echos 'key1'

0

今天,我不得不搜索POST请求返回的数组的第一个键。(并记下表单ID的编号等)

好吧,我发现了这一点: 在PHP中返回关联数组的第一个键

http://php.net/key

我已经做到了,并且有效。

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

也许它将节省15分钟的另一个人。CYA。


-2

你可以玩你的数组

$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';

要获取数组的第一个元素,可以使用current,最后一个元素,可以使用end

编辑

只是为了避免对该答案失去更多的否决权,您可以使用array_keys并使用,将密钥转换为价值,如上所示。


1
这些是值,而不是键。
维克多·施罗德
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.