【问题标题】:Get first key in a (possibly) associative array?获取(可能)关联数组中的第一个键?
【发布时间】:2010-11-04 22:43:35
【问题描述】:

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

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

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

【问题讨论】:

  • 为什么foreach效率低?
  • 对比所有的答案,foreach 仍然是最快的FIDDLE, PHP 5.3,我在 PHP 5.5 上的 localhost 测试表明,差异稍微有利于 foreach。
  • @Danijel, foreach 在语义上是错误的。
  • @AlexS,each($arr)['key']each($arr)[0] 都可以。
  • @Danijel 不再...键:0.0107,foreach:0.0217

标签: php arrays


【解决方案1】:

2019 年更新

PHP 7.3 开始,有一个名为 array_key_first() 的新内置函数,它将从给定数组中检索第一个键,而无需重置内部指针。查看documentation 了解更多信息。


您可以使用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)

【讨论】:

  • 附带说明,reset() 也恰好返回任何数组的第一个元素(值,而不是键),这也很方便。
  • reset() 的文档中有一条评论说Don't use reset()` 以获取关联数组的第一个值。它适用于真正的数组,但在 Iterator 对象上却出人意料。 bugs.php.net/bug.php?id=38478`这仍然是真的吗?我很困惑
  • @DmitryPashkevich:别担心那个评论。他们不是在谈论 array 对象,而是自定义对象(不是实际的数组)。我猜他们混淆了数据结构的差异,但基本上,reset 返回第一个“键”的值,在“错误”报告中给出的示例中,对象将是 $prop,但对于数组第一把钥匙。所以不用担心,只要你使用真正的数组(用array(…)创建),你不会有问题的。
  • 应该提到end()和reset()都有副作用。然而,世界上大多数代码并不依赖于内部指针在任何地方,所以这通常不是问题。
  • @user3019105 每个数组只有一个内部指针,这意味着如果您的函数之外的任何代码更改它(通过调用nextresetend 或遍历数组) , 调用key 时不会得到预期值。所以,是的,在使用key 之前,请务必致电reset,以确保您得到您想要的。
【解决方案2】:

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

【讨论】:

  • 只是给未来读者的一个(迟到的)说明:后一种方法不仅仅是“稍微”快一些。迭代整个数组、将每个键存储在另一个新创建的数组中以及将数组的第一个键请求为字符串之间存在很大差异。
  • 与所有这些答案相比,为什么问题中的操作效率低下?
  • @EmilioGort 好问题。我认为foreach + breakreset + key 实际上的性能没有任何区别。但是前者看起来比较奇怪,所以对于风格问题,我更喜欢后者。
  • @EmilioGort:Afaik,foreach() 在内部复制数组。所以我们可以假设它更慢。 (如果有人能证实这一点会很好)
  • @donquixote 我不确定,但假设它是一个常规数组(而不是实现某种类型或 Iterator 接口的对象),我相当确定 foreach 不会创建它的内部副本,而只是迭代一个指针,类似于使用更底层的nextcurrent 等。
【解决方案3】:

有趣的是,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 />";

在我的 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
foreach http://3v4l.org/gRoGD/perf#tabs

【讨论】:

  • 你有基准测试吗?就像您如何测试等一样。无论如何,感谢您运行它们!
  • 我想指出一个事实,即在整个测试中使用了相同的数组。我认为这一事实显着影响了 foreach 方法。正如@donquixote 在对上述某些回复的评论中提到的那样 - foreach 在内部复制了数组。我可以想象在运行基准测试时会重用此副本,因为避免数组复制仅在此测试中提高性能。
  • @Jarda 从 php7 开始,foreach 从不复制数组,除非您在 foreach 循环中直接修改它。在 php5 上,在某些情况下可以复制数组结构(当它的 refcount > 1 时),您实际上是对的,它可能在那里产生重大影响。幸运的是,在解决此问题的 php7 上无需担心。 Here 很好地了解了 foreach 现在是如何工作的,以及它过去是如何工作的。
  • php7.2 使用上述基准测试,foreach 仍然是最快的
【解决方案4】:

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

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

【讨论】:

  • 记住数组的指针可能不在第一个元素,看我的回答。
  • 我认为这个答案会在不重置的情况下帮助我的情况,因为我首先要确保数组只有一个元素。谢谢
【解决方案5】:

你可以试试

array_keys($data)[0]

【讨论】:

    【解决方案6】:

    2018 年以上

    从 PHP 7.3 开始,有一个 array_key_first() 函数可以实现这一点:

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

    文档可在here 获得。 ?

    【讨论】:

      【解决方案7】:
      list($firstKey) = array_keys($yourArray);
      

      【讨论】:

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

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

      示例:

      # 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))。

      HTH

      【讨论】:

      • array_keys($arr)[0] 语法是否有效?
      • 它在 PHP 5.4 中。它被称为array dereferencing。例如:schlueters.de/blog/archives/…
      • @trante,除了 PHP
      【解决方案9】:

      请查找以下内容:

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

      Working Example:

      【讨论】:

        【解决方案10】:
        $myArray = array(
            2 => '3th element',
            4 => 'first element',
            1 => 'second element',
            3 => '4th element'
        );
        echo min(array_keys($myArray)); // return 1
        

        【讨论】:

        • @jurgemaister max() 不会返回 assoc 数组的第一个键。 max 返回列表或数组项的最大值
        • 不是 OP 请求,但在某些情况下非常有用。
        【解决方案11】:

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

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

        我已经测试过了,它可以工作。

        Working Code.

        【讨论】:

        • array_flip(): 只能翻转 STRING 和 INTEGER 值!
        【解决方案12】:

        为了增强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 秒)。

        【讨论】:

          【解决方案13】:
           $arr = array('key1'=>'value1','key2'=>'value2','key3'=>'key3');
           list($first_key) = each($arr);
           print $first_key;
           // key1
          

          【讨论】:

            【解决方案14】:

            这是我发现的最简单的方法。速度快而且只有两行代码:-D

            $keys = array_keys($array);
            echo $array[$keys[0]];
            

            【讨论】:

              【解决方案15】:

              对我来说最好的方法是

              array_shift(array_keys($array))
              

              array_keys 从初始数组中获取键数组,然后array_shift 从中删除第一个元素值。 为此,您需要 PHP 5.4+。

              【讨论】:

                【解决方案16】:

                php73:

                $array = ['a' => '..', 'b' => '..'];
                
                array_key_first($array); // 'a'
                array_key_last($array); // 'b';
                

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

                【讨论】:

                • 包含解释确实有助于提高帖子的质量。请记住,您是在为将来的读者回答问题,而这些人可能不知道您提出代码建议的原因
                【解决方案17】:

                PHP 7.3.0 起函数array_key_first() 可以使用了。

                有几种方法可以为 PHP 7.3.0 之前的版本提供此功能。可以使用array_keys(),但这可能效率很低。也可以使用reset()key(),但这可能会改变内部数组指针。一个高效的解决方案,不改变内部数组指针,写成polyfill:

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

                【讨论】:

                  【解决方案18】:

                  关于@Blixt 的回答,在 7.3.0 之前,可以使用这个 polyfill:

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

                  【讨论】:

                    【解决方案19】:

                    这适用于所有 PHP 版本

                    $firstKey = '' ;
                    
                    //$contact7formlist - associative array. 
                    
                    if(function_exists('array_key_first')){
                        
                        $firstKey = array_key_first($contact7formlist);
                        
                    }else{
                        
                        foreach ($contact7formlist as $key => $contact7form ){
                            $firstKey = $key;
                            break;
                        }
                    }
                    

                    【讨论】:

                      【解决方案20】:

                      单行:

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

                      【讨论】:

                        【解决方案21】:

                        今天我必须搜索 POST 请求返回的数组的第一个键。 (并记下表单 ID 等的数字)

                        嗯,我发现了这个: Return first key of associative array in PHP

                        http://php.net/key

                        我已经这样做了,它有效。

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

                        也许它会让另一个人生态 15 分钟。 青蒿素。

                        【讨论】:

                          【解决方案22】:

                          我认为最好和最快的方法是:

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

                          【讨论】:

                            【解决方案23】:

                            你可以玩你的数组

                            $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 将您的键转换为值,并如上所示使用。

                            【讨论】:

                            • 这些是值,而不是键。
                            【解决方案24】:

                            使用:

                            $array = ['po','co','so'];
                            
                            echo reset($array); 
                            

                            结果:po

                            【讨论】:

                              猜你喜欢
                              • 2013-04-23
                              • 2015-06-26
                              • 2015-03-03
                              • 1970-01-01
                              • 2011-10-05
                              • 2015-11-14
                              • 2011-05-28
                              相关资源
                              最近更新 更多