ChatGPT解决这个技术问题 Extra ChatGPT

获取数组的第一个元素

我有一个数组:

array( 4 => 'apple', 7 => 'orange', 13 => 'plum' )

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

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

我怎样才能做到这一点?

你是什么意思,不能通过引用来完成?
函数不应该使用 &$array 作为参数。
我怀疑你“真正”的意思是“不能通过引用来完成”,是你的数组是从数据库中动态返回的,并且你不想在获取第一个元素之前将数组传递给变量从中。如果我是对的,那么下面提供给您的所有解决方案中的绝大多数(包括接受的答案)都是不够的。
您只需要获取它还是获取它并将其从现有阵列中删除?
对于阵列的基本使用,您可以查看此链接 technofusions.com/introduction-to-arrays-in-php

P
Peter Mortensen

原始答案,但代价高昂(O(n)):

array_shift(array_values($array));

在 O(1) 中:

array_pop(array_reverse($array));

其他用例等...

如果修改(在重置数组指针的意义上)$array 不是问题,您可以使用:

reset($array);

如果需要数组“副本”,这在理论上应该更有效:

array_shift(array_slice($array, 0, 1));

使用 PHP 5.4+(但如果为空可能会导致索引错误):

array_values($array)[0];

+1 用于防止使用 array_values() 修改原始数组的巧妙解决方法
我明白了:严格标准:只有变量应该通过引用传递。顺便说一句,很好的解决方法
这不是有点矫枉过正吗?如果数组包含数千个元素怎么办?仅仅为了获得它的第一个元素而创建一个全新的数组是否合理? list()reset() 在我看来是更好的解决方案。
我同意。与重置并返回当前值的一行相比,总的过度杀伤和异常资源繁重:reset($array);
-1 正如上述评论者所说。令我困惑的是,这有 101 个赞成票。
T
Tom

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

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

如果要获取密钥:(reset后执行)

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

PHP's documentation

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

描述:

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


虽然它是通过引用传递给reset,但原始数组并没有被修改。我猜这就是 hsz 不想通过引用传递它的原因..?
数组的迭代器被修改。如果您在主题数组的 foreach 中执行此操作,您会搞砸的。
@Zenexer 这并不总是(通常)正确。通常在实践中,foreach 将复制它循环通过的数组。
@Angger 重置后,您可以拨打 key($arr),您将得到“4”(添加到答案中)
@Zenexer 和 Luke Cousins 都不是正确的:1) foreach 不使用数组的内部指针 - 而是创建它自己的指针。很容易检查 foreach 中的 reset 调用 - 循环将按照它的方式进行,而 reset() 没有任何影响。 2) 不,foreach 不会创建数组的副本!!!它只创建它自己的指针(甚至不是现有指针的副本 - 它也很容易检查,在 foreach 之前调用 next())。
P
Peter Mortensen
$first_value = reset($array); // First element's value
$first_key = key($array); // First element's key

我还没有实际测试过它,但似乎这种方法是最有效的。
唯一的问题是询问值的问题,而不是键。因此应该使用 current($array) 而不是 key($array)
@zmonteca $first_value = reset($array);在这里你得到值,reset() 函数回退数组内部指针并返回第一个元素。
最好的答案!正在寻找 key() 等价性来获得第一个值。这有帮助!
如果数组为空怎么办? reset() 将返回 false,如果您希望数组包含 bool 值,这可能会导致错误。
T
Tofeeq

current($array)

返回数组的第一个元素 according to the PHP manual

每个数组都有一个指向其“当前”元素的内部指针,该元素被初始化为插入到数组中的第一个元素。

所以它一直有效,直到您重新定位数组指针,否则您将不得不使用 reset() 它将倒回数组并返回数组的第一个元素

According to the PHP manual reset

reset() 将数组的内部指针倒回到第一个元素并返回第一个数组元素的值。

current()reset() 的示例

$array = array('step one', 'step two', 'step three', 'step four');

// by default, the pointer is on the first element
echo current($array) . "<br />\n"; // "step one"

//Forward the array pointer and then reset it

// skip two steps
next($array);
next($array);
echo current($array) . "<br />\n"; // "step three"

// reset pointer, start again on step one
echo reset($array) . "<br />\n"; // "step one"

我不知道为什么这不是公认的答案,因为它相当简单准确地回答了这个问题。
current($array) 仅在数组指针“当前”指向第一个元素时才有效,否则需要 reset($array)
似乎 current() 不再需要参考,尽管 PHP 文档没有反映这一点。所以我认为这已经成为最好的解决方案。
@Ryan 同意,但这个解决方案是在 2014 年之前 2 年在 this other answer of this same thread 中给出的......奇怪的是这个不完整的句子得到了更多的支持。
如果数组为空怎么办? reset()current() 将返回 false,如果您希望数组包含 bool 值,这可能会导致错误。
M
Martin
$arr = $array = array( 9 => 'apple', 7 => 'orange', 13 => 'plum' );
echo reset($arr); // echoes 'apple'

如果您不想丢失当前指针位置,只需为数组创建一个别名。


没看懂,什么意思?第一个键是否比其他键大,它工作正常。
+1 仅供参考 reset() 已经返回第一个元素,因此无需使用 current() - echo reset($arr) 就足够了
@Mike 但您可能更喜欢 current 而不是 reset 以避免在参考案例(例如 current(array_filter(...)); in 3v4l)中产生 PHP 通知/错误。
如果数组为空怎么办? reset() 将返回 false,如果您希望数组包含 bool 值,这可能会导致错误。
A
Alex Shesterov

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

array_key_first

array_key_last

除了在语义上有意义之外,这些函数甚至不移动数组指针(就像 foreach 所做的那样)。

有了键,可以直接通过键获取值。

示例(所有这些都需要 PHP 7.3+)

获取第一个/最后一个键和值:

$my_array = ['IT', 'rules', 'the', 'world'];

$first_key = array_key_first($my_array);
$first_value = $my_array[$first_key];

$last_key = array_key_last($my_array);
$last_value = $my_array[$last_key];

假设数组不能为空,将第一个/最后一个值作为单行:

$first_value = $my_array[ array_key_first($my_array) ];

$last_value = $my_array[ array_key_last($my_array) ];

获取第一个/最后一个值作为单行,默认为空数组:

$first_value = empty($my_array) ? 'default' : $my_array[ array_key_first($my_array) ];

$last_value = empty($my_array) ? 'default' : $my_array[ array_key_last($my_array) ];

null-coalescing operator 缩短,通常默认为 null,因此:$first_value = $my_array[array_key_first($my_array)] ?? null;
从 PHP 7.3 开始,这应该是选定的答案。
P
Peter Mortensen

您可以使用语言构造“list”获取第 N 个元素:

// First item
list($firstItem) = $yourArray;

// First item from an array that is returned from a function
list($firstItem) = functionThatReturnsArray();

// Second item
list( , $secondItem) = $yourArray;

使用 array_keys 函数,您可以对键执行相同操作:

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

这正是我所做的:list($first_value) = $my_array; 在我看来,这是最好的选择。它没有此处提供的其他答案的问题:没有“矫枉过正”,因为它不复制数组或创建新数组。没有“引用”:数组没有被修改。没有“重置”:没有更改数组内部指针......
非常优雅的解决方案,但是当数组为空时会抛出 E_NOTICE。
这不是错了吗?!仅当数组键为 int 时才有效,尝试执行 list($firstItem) = array('key1' => 'value1'); 会出现错误 Notice: Undefined offset: 0
@Sergiy 但是你失去了这个解决方案的最大优势,这并不是将整个原始数组不必要地复制到另一个数组。尽管如此,假设您可以保证整数索引数组的好处,+1
澄清一下:list($x) = foo(); 等同于 $x = foo()[0];。请注意,这不一定与“获取第一项”相同,因为即使是整数索引数组也可能没有键为 0 的元素。在我的情况下,我正在执行“list($order) = get_order($user) ;"但是“get_order”返回的是由 ID 键入的订单,该 ID 通常不是 0。正如 @Sergiy 所说,array_values() 解决了这个问题,但降低了代码的效率和(更重要的是)可读性。
h
hsz

PHP 5.4+:

array_values($array)[0];

他在 2013 年 10 月编辑了他的答案,以包括我在 4 月添加的答案。
PHP 4:$array_values = array_values($array); $value = $array_values[0];
如果数组为空,它将返回 undefined key 0,因此请谨慎使用
L
Lee Benson

某些数组不适用于 listresetcurrent 等函数。也许它们是“人造”数组——例如,部分实现了 ArrayIterator。

如果您想提取第一个值而不考虑数组,您可以将迭代器短路:

foreach($array_with_unknown_keys as $value) break;

然后,您的值将在 $value 中可用,并且循环将在第一次迭代后中断。这比将可能很大的数组复制到像 array_unshift(array_values($arr)) 这样的函数更有效。

您也可以通过以下方式获取密钥:

foreach($array_with_unknown_keys as $key=>$value) break;

如果您从函数中调用它,只需提前返回:

function grab_first($arr) {
    foreach($arr as $value) return $value;
}

我想这是最快的方法之一,因为使用语言构造 foreach 而不是函数调用(更昂贵)。 designcise.com/web/tutorial/…
h
hsz

认为:

$array = array( 4 => 'apple', 7 => 'orange', 13 => 'plum' );

只需使用:

$array[key($array)]

获取第一个元素或

key($array)

获得第一把钥匙。

或者,如果您想删除它,您可以取消第一个链接。


那么不简单地使用 current 呢?
P
Peter Mortensen

Laravel's helpers

function head($array)
{
    return reset($array);
}

数组按值传递给函数,reset() 影响数组副本的内部指针,并且它不接触原始数组(注意,如果数组为空,它会返回 false)。

使用示例:

$data = ['foo', 'bar', 'baz'];

current($data); // foo
next($data); // bar
head($data); // foo
next($data); // baz

此外,这里还有一个替代方案。它的速度非常快,但更有趣。如果数组为空,它可以轻松更改默认值:

function head($array, $default = null)
{
    foreach ($array as $item) {
        return $item;
    }
    return $default;
}

作为记录,这里是 another answer of mine,表示数组的最后一个元素。


t
tfont

保持简单!这里有很多正确的答案,但是为了尽量减少所有的混淆,这两个工作并减少了很多开销:

key($array) 获取数组的第一个键
current($array) 获取数组的第一个值


编辑:
关于以下评论。以下示例将输出:string(13) "PHP code test"

$array = array
(
   '1'           => 'PHP code test',  
   'foo'         => 'bar', 5 , 5 => 89009, 
   'case'        => 'Random Stuff: '.rand(100,999),
   'PHP Version' => phpversion(),
   0             => 'ending text here'
);

var_dump(current($array));

呃。 current 等于当前元素。您必须将指针重置为数组的开头,以确保它实际上位于开头。
current() 将获取当前元素,而不是第一个元素。这不一样。
如果数组中只有一个元素, current 将起作用。
P
Peter Mortensen

只需这样做:

array_shift(array_slice($array,0,1));

这是一种没有吸引力(且无法解释)的技术,因为有单一调用技术可以实现相同的目标。
u
user1485518

我会做 echo current($array)


@hsz 没关系,current() 在传递非引用时不会出错。如果指针仍然在开头,则此方法有效。
但它会产生一个通知,使您的日志变脏并且很好......如果它们不重要,您也应该摆脱通知
@dmikam 不,它没有。实际上 reset 会产生“只有变量应该通过引用传递”的通知,而 current 不会:Online PHP Editor example of current(array_filter(...));
@CPHPython,看起来你是对的......看起来我从 PHP 4 的旧时代就有这个想法,它确实会产生致命错误:sandbox.onlinephpfunctions.com/code/… 我在使用 current 时看到的唯一问题是它不能保证返回的元素是数组的第一个元素(内部指针可能被调用函数修改)。实际上,它可能会返回数组的随机元素。
@CPHPython 有点人为的例子,但它很好地展示了我的想法:sandbox.onlinephpfunctions.com/code/… 想象一下,您从使用 next()end() 或任何其他修改数组内部指针的函数的函数接收数组。在我的示例中,current() 返回 null,因为内部指针超出了数组的范围。但它也可能“实际上”指向任何/随机元素。
P
Pang
$arr = array( 4 => 'apple', 7 => 'orange', 13 => 'plum' );
foreach($arr as $first) break;
echo $first;

输出:

apple

A
AndreyP

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));
    }
}
?>

P
Peter Mortensen
$myArray = array (4 => 'apple', 7 => 'orange', 13 => 'plum');
$arrayKeys = array_keys($myArray);

// The first element of your array is:
echo $myArray[$arrayKeys[0]];

r
rustyx
$array=array( 4 => 'apple', 7 => 'orange', 13 => 'plum' );

$firstValue = each($array)[1];

这比 array_values() 高效得多,因为 each() 函数不会复制整个数组。

有关详细信息,请参阅 http://www.php.net/manual/en/function.each.php


because the each() function does not copy the entire array. +1
但问题是您应该在之前进行重置,如果内部指针不在开头,您将不会获得第一个元素。
但是 each() 通过引用接收一个数组,并且初始问题的要求不是这样做
P
Peter Mortensen

一个笨拙的方法是:

$foo = array( 4 => 'apple', 7 => 'orange', 13 => 'plum' );

function get_first ($foo) {
    foreach ($foo as $k=>$v){
        return $v;
    }
}

print get_first($foo);

至少你是诚实的——它很笨拙!但是,它有效,我过去一直使用它,直到学习上面的 list() 技术。
如果您这样做,您不妨使用 reset(),因为在调用 foreach 之前重置数组指针。
t
tfont

大多数这些工作!但是对于快速单行(低资源)调用:

$array = array( 4 => 'apple', 7 => 'orange', 13 => 'plum' );
echo $array[key($array)];

// key($array) -> will return the first key (which is 4 in this example)

虽然这很有效,而且还不错,但也请参阅我的附加答案:https://stackoverflow.com/a/48410351/1804013


这等效于使用 current($array),它要求数组的内部指针无论如何都位于第一个元素,在这种情况下,echo reset($array) 是最合适的。
@Tyzoid 他实际上写了 another answer here with your suggestion,但他省略了你的解释......谢谢。
@Tyzoid:我做了一个额外的答案/更新一会儿去:stackoverflow.com/a/48410351/1804013
P
Peter Mortensen

利用:

$first = array_slice($array, 0, 1);  
$val= $first[0];

默认情况下,array_slice 不保留键,因此我们可以安全地使用零作为索引。


C
Chris Kempen

这对游戏来说有点晚了,但是我遇到了一个问题,我的数组包含数组元素作为其中的子元素,因此我不能只获得第一个数组元素的字符串表示形式。通过 using PHP's current() function,我做到了:

<?php
    $original = array(4 => array('one', 'two'), 7 => array('three', 'four'));
    reset($original);  // to reset the internal array pointer...
    $first_element = current($original);  // get the current element...
?>

感谢所有当前的解决方案帮助我得到这个答案,我希望这对某人有所帮助!


M
Mahdi Bashirpour
<?php
    $arr = array(3 => "Apple", 5 => "Ball", 11 => "Cat");
    echo array_values($arr)[0]; // Outputs: Apple
?>

其他示例:

<?php
    $arr = array(3 => "Apple", 5 => "Ball", 11 => "Cat");
    echo current($arr); // Outputs: Apple
    echo reset($arr); // Outputs: Apple
    echo next($arr); // Outputs: Ball
    echo current($arr); // Outputs: Ball
    echo reset($arr); // Outputs: Apple
?>

该答案的哪一部分为页面带来了新信息?
j
jmking

我认为在这里使用 array_values 是最好的选择。您可以从该函数的结果返回索引为零的值以获取“苹果”。


P
Peter Mortensen

为您提供两种解决方案。

解决方案 1 - 只需使用密钥。你还没有说你不能使用它。 :)

<?php
    // Get the first element of this array.
    $array = array( 4 => 'apple', 7 => 'orange', 13 => 'plum' );

    // Gets the first element by key
    $result = $array[4];

    // Expected result: string apple
    assert('$result === "apple" /* Expected result: string apple. */');
?>

解决方案 2 - array_flip() + key()

<?php
    // Get first element of this array. Expected result: string apple
    $array = array( 4 => 'apple', 7 => 'orange', 13 => 'plum' );

    // Turn values to keys
    $array = array_flip($array);

    // You might thrown a reset in just to make sure
    // that the array pointer is at the first element.
    // Also, reset returns the first element.
    // reset($myArray);

    // Return the first key
    $firstKey = key($array);

    assert('$firstKey === "apple" /* Expected result: string apple. */');
?>

解决方案 3 - array_keys()

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

p
pgee70

没有人建议使用 ArrayIterator 类:

$array = array( 4 => 'apple', 7 => 'orange', 13 => 'plum' );
$first_element = (new ArrayIterator($array))->current();
echo $first_element; //'apple'

绕过 OP 的参考规定。


这应该是正确的答案。也可以获取第一个键:(new ArrayIterator($array))->key()。请注意,当数组为空时,它会正确返回值和键的 null(而不是返回像 false 这样的伪值)。不幸的是,它不适用于 Laravel 的 Collection 类,它总是返回 null
P
Peter Mortensen

我想作者只是在寻找一种方法来在从某个函数(例如 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 消息,也不会创建任何额外的数组。它适用于索引和关联数组。


A
Ataboy Josef

使用 array_keys() 以数字索引数组的形式访问关联数组的键,然后可以再次将其用作数组的键。

解决方案为 arr[0] 时:

(注意,由于带有键的数组是从 0 开始的索引,所以第一个元素是索引 0)

您可以使用一个变量,然后减去一个,以获得您的逻辑,即 1 => 'apple'

$i = 1;
$arr = array( 4 => 'apple', 7 => 'orange', 13 => 'plum' );
echo $arr[array_keys($arr)[$i-1]];

输出:

apple

好吧,为简单起见 - 只需使用:

$arr = array( 4 => 'apple', 7 => 'orange', 13 => 'plum' );
echo $arr[array_keys($arr)[0]];

输出:

apple

通过第一种方法,不仅是第一个元素,而且可以将关联数组视为索引数组。


J
Jesse

我不喜欢摆弄数组的内部指针,但是用 array_keys()array_values() 构建第二个数组也是低效的,所以我通常这样定义:

function array_first(array $f) {
    foreach ($f as $v) {
        return $v;
    }
    throw new Exception('array was empty');
}

P
Peter Mortensen

这在现实世界中并不是那么简单的反应。假设我们有这些可能的响应示例,您可以在某些库中找到这些示例。

$array1 = array();
$array2 = array(1,2,3,4);
$array3 = array('hello'=>'world', 'foo'=>'bar');
$array4 = null;

var_dump('reset1', reset($array1));
var_dump('reset2', reset($array2));
var_dump('reset3', reset($array3));
var_dump('reset4', reset($array4)); // Warning

var_dump('array_shift1', array_shift($array1));
var_dump('array_shift2', array_shift($array2));
var_dump('array_shift3', array_shift($array3));
var_dump('array_shift4', array_shift($array4)); // Warning

var_dump('each1', each($array1));
var_dump('each2', each($array2));
var_dump('each3', each($array3));
var_dump('each4', each($array4)); // Warning

var_dump('array_values1', array_values($array1)[0]); // Notice
var_dump('array_values2', array_values($array2)[0]);
var_dump('array_values3', array_values($array3)[0]);
var_dump('array_values4', array_values($array4)[0]); // Warning

var_dump('array_slice1', array_slice($array1, 0, 1));
var_dump('array_slice2', array_slice($array2, 0, 1));
var_dump('array_slice3', array_slice($array3, 0, 1));
var_dump('array_slice4', array_slice($array4, 0, 1)); // Warning

list($elm) = $array1; // Notice
var_dump($elm);
list($elm) = $array2;
var_dump($elm);
list($elm) = $array3; // Notice
var_dump($elm);
list($elm) = $array4;
var_dump($elm);

如您所见,我们有几种“单线”解决方案在某些情况下效果很好,但并非全部。

在我看来,您应该只使用数组处理该处理程序。

现在谈论性能,假设我们总是有数组,像这样:

$elm = empty($array) ? null : ...($array);

...you would use without errors:
$array[count($array)-1];
array_shift
reset
array_values
array_slice

array_shiftreset 快,即比 [count()-1] 快,这三个比 array_valuesarray_slice 快。