我有一个数组:

阵列(4 = > '苹果',7 = >“橙色”,13 = >“李子”)

我想要得到这个数组的第一个元素。预期结果:串苹果

一个要求:它不能通过引用传递来完成,所以array_shift不是一个好的解决方案。

我该怎么做呢?


当前回答

PHP 7.3添加了两个函数,用于直接获取数组的第一个和最后一个键,而无需修改原始数组,也无需创建任何临时对象:

array_key_first array_key_last

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

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

if (!function_exists('array_key_last')) {
    function array_key_last($arr) {
        return array_key_first(array_reverse($arr, true));
    }
}
?>

其他回答

正如Mike指出的(最简单的方法):

$arr = array( 4 => 'apple', 7 => 'orange', 13 => 'plum' );
echo reset($arr); // Echoes "apple"

如果你想获取密钥:(重置后执行)

echo key($arr); // Echoes "4"

来自PHP的文档:

混合重置(数组|对象和$array);

描述:

reset()返回数组的内部指针指向第一个元素并返回第一个元素的值,如果数组为 空的。

我想象作者只是在寻找一种方法来获得一个数组的第一个元素后,从一些函数(mysql_fetch_row,例如),而不生成一个严格的“只有变量应该通过引用传递”。

如果是这样的话,这里描述的几乎所有方法都会得到这个消息…其中一些会使用大量额外的内存来复制一个数组(或其中的一部分)。避免它的一个简单方法是在调用任何这些函数之前内联赋值:

$first_item_of_array = current($tmp_arr = mysql_fetch_row(...));
// or
$first_item_of_array = reset($tmp_arr = func_get_my_huge_array());

这样就不会在屏幕上看到STRICT消息,也不会在日志中看到STRICT消息,也不会创建任何额外的数组。它既适用于索引数组,也适用于关联数组。

查找数组中的第一个和最后一个项:

// Get the first item in the array
print $array[0]; // Prints 1

// Get the last item in the array
print end($array);

我喜欢“列表”的例子,但是“列表”只适用于赋值的左边。如果我们不想赋值一个变量,我们将被迫创建一个临时名称,这在最好的情况下会污染我们的作用域,在最坏的情况下会覆盖现有的值:

list($x) = some_array();
var_dump($x);

上面的代码将覆盖$x的任何现有值,只要这个作用域是活动的,$x变量就会一直存在(函数/方法的结束,如果我们在顶层,则永远存在)。这可以使用call_user_func和一个匿名函数来解决,但它很笨拙:

var_dump(call_user_func(function($arr) { list($x) = $arr; return $x; },
                        some_array()));

如果我们使用这样的匿名函数,我们实际上可以避开reset和array_shift,即使它们使用引用传递。这是因为调用一个函数会绑定它的参数,这些参数可以通过引用传递:

var_dump(call_user_func(function($arr) { return reset($arr); },
                        array_values(some_array())));

然而,这实际上是多余的,因为call_user_func将在内部执行这个临时赋值。这让我们可以像处理值传递一样处理引用传递函数,没有任何警告或错误:

var_dump(call_user_func('reset', array_values(some_array())));

同样值得记住的是您执行此操作的上下文,因为详尽的检查可能是昂贵的,而且并不总是必要的。

例如,这个解决方案在我使用它的情况下工作得很好(但显然不能在所有情况下都依赖它……)

 /**
 * A quick and dirty way to determine whether the passed in array is associative or not, assuming that either:<br/>
 * <br/>
 * 1) All the keys are strings - i.e. associative<br/>
 * or<br/>
 * 2) All the keys are numeric - i.e. not associative<br/>
 *
 * @param array $objects
 * @return boolean
 */
private function isAssociativeArray(array $objects)
{
    // This isn't true in the general case, but it's a close enough (and quick) approximation for the context in
    // which we're using it.

    reset($objects);
    return count($objects) > 0 && is_string(key($objects));
}