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

Ale*_*x S 729 php arrays

确定可能关联数组中第一个键的最佳方法是什么?我第一次认为它只是预先处理数组,然后立即打破它,如下所示:

foreach ($an_array as $key => $val) break;
Run Code Online (Sandbox Code Playgroud)

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

Bli*_*ixt 1292

你可以使用array_key_first()reset:

reset($array);
$first_key = key($array);
Run Code Online (Sandbox Code Playgroud)

它与您的初始代码基本相同,但开销较少,而且更明显的是发生了什么.

只记得打电话key,或者你可以获得阵列中的任何键.您也可以使用reset而不是end获取最后一个键.

如果你想让键获得第一个值,reset实际返回它:

$first_value = reset($array);
Run Code Online (Sandbox Code Playgroud)

有一个特殊情况需要注意(所以首先检查数组的长度):

$arr1 = array(false);
$arr2 = array();
var_dump(reset($arr1) === reset($arr2)); // bool(true)
Run Code Online (Sandbox Code Playgroud)

  • 作为旁注,`reset()`也会返回任何数组的第一个元素(值,而不是键),这也很方便. (137认同)
  • @DmitryPashkevich:不要担心这个评论.他们不是在讨论`array`对象,而是自定义对象(不是实际的数组).我猜他们混淆了数据结构的差异,但基本上,`reset`返回第一个"key"的值,对于在"bug"报告中给出的示例中对象将是`$ prop`,但是对于数组第一个键.所以不要担心,只要你使用真正的数组(用`array(...)`创建),你就不会有问题. (13认同)
  • 文档中有一条注释要求`reset()`说`不要使用`reset()`来获取关联数组的第一个值.它适用于真正的数组,但在Iterator对象上意外工作.http://bugs.php.net/bug.php?id = 38478`这仍然是真的吗?我糊涂了 (5认同)
  • 应该提到的是end()和reset()有副作用。但是,世界上大多数代码都不依赖于内部指针在任何地方,因此这通常不是问题。 (2认同)

tro*_*skn 76

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

  • 对于未来的读者来说,这只是一个(后期)的注释:后一种方法不仅仅是"略微"加快.迭代整个数组,将每个键存储在另一个新创建的数组中,并将数组的第一个键作为字符串请求之间存在很大差异. (49认同)
  • @EmilioGort好问题.实际上,我认为`foreach` +`break`和`reset` +`key`的性能没有任何差别.但前者看起来很奇怪,所以对于风格问题,我更喜欢后者. (5认同)
  • 与所有这些答案相比,为什么问题中的op效率低? (3认同)
  • @donquixote我不确定,但假设它是一个常规数组(而不是实现某种类型或Iterator接口的对象),我很确定`foreach`不会为它创建内部副本,而只是迭代指针,类似于使用更低级别的"next","current"等. (3认同)

Web*_*mut 53

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

由于OP专门询问了效率,因此应该指出的是,目前所有的答案实际上都比foreach低得多.

我使用php 5.4对此进行了基准测试,并且重置/键指针方法(接受的答案)似乎比foreach慢约7倍.操纵整个阵列(array_keys,array_flip)其他方法显然比这还要慢,成为很多有大阵工作时更糟糕.

Foreach效率不高,随意使用!

编辑2015-03-03:

已经请求了基准脚本,我没有原始脚本,而是进行了一些新的测试.这次我发现foreach的速度只有reset/key的两倍.我使用了一个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 />";
Run Code Online (Sandbox Code Playgroud)

在我的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
Run Code Online (Sandbox Code Playgroud)

复位+键http://3v4l.org/b4DrN/perf#tabs
foreach http://3v4l.org/gRoGD/perf#tabs

  • 你有什么基准吗?就像你测试的等等.无论如何,谢谢你运行它们! (3认同)
  • @Jarda从php7开始,`foreach`永远不会复制该数组,除非您直接在foreach循环内对其进行修改。在php5上,可以在某些情况下复制数组结构(当其refcount&gt; 1时),实际上您是对的,这可能会对那里产生重大影响。幸运的是,在此问题已解决的php7上,无需担心。[这里](/sf/ask/704037001/?noredirect=1&amp;lq=1)'很好地阅读了关于foreach现在如何工作以及如何工作的信息过去工作过。 (2认同)
  • 截至使用上述基准的php7.2,foreach仍然最快 (2认同)

jim*_*myi 36

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

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

  • 请记住,数组的指针可能不在第一个元素,请参阅我的答案. (6认同)

小智 23

你可以试试

array_keys($data)[0]
Run Code Online (Sandbox Code Playgroud)


iva*_*obd 22

对于2018+

从PHP 7.3开始,有一个array_key_first()功能可以达到这个目的:

$array = ['foo' => 'lorem', 'bar' => 'ipsum'];
$firstKey = array_key_first($array); // 'foo'
Run Code Online (Sandbox Code Playgroud)

文档可在此处获得.


Ser*_*nko 21

list($firstKey) = array_keys($yourArray);
Run Code Online (Sandbox Code Playgroud)

  • @Yada,是的,但在极少数情况下这可能会引人注目; 在大多数情况下,可读性和可维护性更为重要; 而且我也更喜欢不改变原始对象/数组的解决方案:例如reset($ ar); $ key = key($ ar); - 并不总是好主意,我宁愿选择比我更简洁的MartyIX解决方案,例如:array_keys($ ar)[0]; (3认同)
  • 这可能不是最有效的。 (2认同)

Mar*_*cka 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"
Run Code Online (Sandbox Code Playgroud)

优于解决方案的优势:

list($firstKey) = array_keys($yourArray);
Run Code Online (Sandbox Code Playgroud)

是你可以array_keys($arr)[0]作为函数参数传递(即doSomething(array_keys($arr)[0], $otherParameter)).

HTH

  • 它是PHP 5.4.它被称为"数组解除引用".例如:http://schlueters.de/blog/archives/138-Features-in-PHP-trunk-Array-dereferencing.html (5认同)
  • ```array_keys($ arr)[0]```语法是否有效? (3认同)

Pup*_*pil 12

请找到以下内容:

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

我认为这会奏效.


Ham*_*eza 12

$myArray = array(
    2 => '3th element',
    4 => 'first element',
    1 => 'second element',
    3 => '4th element'
);
echo min(array_keys($myArray)); // return 1
Run Code Online (Sandbox Code Playgroud)

  • 不是OP请求,但在某些情况下非常有用. (5认同)

Pup*_*pil 9

这也可以是一种解决方案.

$yourArray = array('first_key'=> 'First', 2, 3, 4, 5);
$first_key = current(array_flip($yourArray));
echo $first_key;
Run Code Online (Sandbox Code Playgroud)

我测试了它,它的工作原理.

  • array_flip():只能翻转STRING和INTEGER值! (3认同)

Pri*_*e80 5

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

$firstKey = array_keys(array_slice($array, 0, 1, TRUE))[0];
Run Code Online (Sandbox Code Playgroud)

我在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 
Run Code Online (Sandbox Code Playgroud)

如果我对大小为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 
Run Code Online (Sandbox Code Playgroud)

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