What's the best way to get the last element of an array without deleting it?
好啊,
我知道所有关于
编辑:这里有一个奖励:
1 |
甚至
1 2 3 |
尝试
1 |
要重置它(谢谢@hopeseker):
1 |
手动链接
@大卫·默多克补充道:
1 | Strict Standards: Only variables should be passed by reference |
谢谢你和所有人!
又矮又甜。
我提出了消除错误消息并保留一个线性形式和有效性能的解决方案:
1 |
--以前的解决方案
1 |
注意:为了避免出现
这条线索中的许多答案为我们提供了许多不同的选择。为了能够从中进行选择,我需要了解他们的行为和表现。在这个答案中,我将与您分享我的发现,以PHP版本
我将测试的选项(
- 选项1。
$x = array_values(array_slice($array, -1))[0]; (由Rolacja建议) - 选项2。
$x = array_slice($array, -1)[0]; (由studie建议) - 选项3。
$x = array_pop((array_slice($array, -1))); (由Rolacja建议) - 选项4。
$x = array_pop((array_slice($array, -1, 1))); (按Westy92建议) - 选项5。
$x = end($array); reset($array); (依伊兹诺古德建议) - 选项6。
$x = end((array_values($array))); (由Tecbrat建议) - 选项7。
$x = $array[count($array)-1]; (由Mirko Pagliai提出) - 选项8。
$keys = array_keys($array); $x = $array[$keys[count($keys)-1]]; (Thru建议) - 选项9。
$x = $array[] = array_pop($array); (用户建议2782001) - 选项10。
$x = $array[array_key_last($array)]; (由quasimodo's clone建议;根据php 7.3提供)
(提到的函数:array_key_last,array_keys,array_pop,array_slice,array_values,count,end,reset)
测试输入(
- 空=
$array = null; 。 - 空=
$array = []; 。 - 最后一个空=
$array = ["a","b","c",null]; 。 - Auto_idx=
$array = ["a","b","c","d"]; 。 - shuffle=
$array = []; $array[1] ="a"; $array[2] ="b"; $array[0] ="c"; 。 - 100=
$array = []; for($i=0;$i<100;$i++) { $array[] = $i; } 。 - 100000=
$array = []; for($i=0;$i<100000;$i++) { $array[] = $i; } 。
为了测试,我将使用
1 | sudo docker run -it --rm php:5.6.38-cli-stretch php -r '<<<CODE HERE>>>' |
上面列出的
1 2 | <<input code>> error_reporting(E_ALL); <<option code>> error_reporting(0); $before=microtime(TRUE); for($i=0;$i<100;$i++){echo".";for($j=0;$j<100;$j++){ <<option code>> }}; $after=microtime(TRUE); echo" "; var_dump($x); echo round(($after-$before)/(100*100)*1000*1000*1000); |
对于每次运行,这将var_转储测试输入的最后一个检索值,并以飞秒(0.0000000000001秒)为单位打印一次迭代的平均持续时间。
结果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | /==========================================================================================================================================================================================================================================================================================================================================================================================================================\ || || T E S T I N P U T - 5 . 6 . 3 8 || T E S T I N P U T - 7 . 2 . 1 0 || T E S T I N P U T - 7 . 3 . 0 R C 1 || || || null | empty | last_null | auto_idx | shuffle | 100 | 100000 || null | empty | last_null | auto_idx | shuffle | 100 | 100000 || null | empty | last_null | auto_idx | shuffle | 100 | 100000 || ||============================OPTIONS - ERRORS==========================++===============+===============+===============+===============+===============+===============+===============++===============+===============+===============+===============+===============+===============+===============++===============+===============+===============+===============+===============+===============+===============<| || 1. $x = array_values(array_slice($array, -1))[0]; || W1 + W2 | N1 | - | - | - | - | - || W1 + W2 | N1 | - | - | - | - | - || W1 + W2 | N1 | - | - | - | - | - || || 2. $x = array_slice($array, -1)[0]; || W1 | N1 | - | - | - | - | - || W1 | N1 | - | - | - | - | - || W1 | N1 | - | - | - | - | - || || 3. $x = array_pop((array_slice($array, -1))); || W1 + W3 | - | - | - | - | - | - || W1 + N2 + W3 | N2 | N2 | N2 | N2 | N2 | N2 || W1 + N2 + W3 | N2 | N2 | N2 | N2 | N2 | N2 || || 4. $x = array_pop((array_slice($array, -1, 1))); || W1 + W3 | - | - | - | - | - | - || W1 + N2 + W3 | N2 | N2 | N2 | N2 | N2 | N2 || W1 + N2 + W3 | N2 | N2 | N2 | N2 | N2 | N2 || || 5. $x = end($array); reset($array); || W4 + W5 | - | - | - | - | - | - || W4 + W5 | N2 | N2 | N2 | N2 | N2 | N2 || W4 + W5 | - | - | - | - | - | - || || 6. $x = end((array_values($array))); || W2 + W4 | - | - | - | - | - | - || W2 + N2 + W4 | - | - | - | - | - | - || W2 + N2 + W4 | N2 | N2 | N2 | N2 | N2 | N2 || || 7. $x = $array[count($array)-1]; || - | N3 | - | - | - | - | - || W7 | N3 | - | - | - | - | - || W7 | N3 | - | - | - | - | - || || 8. $keys = array_keys($array); $x = $array[$keys[count($keys)-1]]; || W6 | N3 + N4 | - | - | - | - | - || W6 + W7 | N3 + N4 | - | - | - | - | - || W6 + W7 | N3 + N4 | - | - | - | - | - || || 9. $x = $array[] = array_pop($array); || W3 | - | - | - | - | - | - || W3 | - | - | - | - | - | - || W3 | - | - | - | - | - | - || || 10. $x = $array[array_key_last($array)]; || F1 | F1 | F1 | F1 | F1 | F1 | F1 || F2 | F2 | F2 | F2 | F2 | F2 | F2 || W8 | N4 | F2 | F2 | F2 | F2 | F2 || ||========================OPTIONS - VALUE RETRIEVED=====================++===============+===============+===============+===============+===============+===============+===============++===============+===============+===============+===============+===============+===============+===============++===============+===============+===============+===============+===============+===============+===============<| || 1. $x = array_values(array_slice($array, -1))[0]; || NULL | NULL | NULL | string(1)"d" | string(1)"c" | int(99) | int(99999) || NULL | NULL | NULL | string(1)"d" | string(1)"c" | int(99) | int(99999) || NULL | NULL | NULL | string(1)"d" | string(1)"c" | int(99) | int(99999) || || 2. $x = array_slice($array, -1)[0]; || NULL | NULL | NULL | string(1)"d" | string(1)"c" | int(99) | int(99999) || NULL | NULL | NULL | string(1)"d" | string(1)"c" | int(99) | int(99999) || NULL | NULL | NULL | string(1)"d" | string(1)"c" | int(99) | int(99999) || || 3. $x = array_pop((array_slice($array, -1))); || NULL | NULL | NULL | string(1)"d" | string(1)"c" | int(99) | int(99999) || NULL | NULL | NULL | string(1)"d" | string(1)"c" | int(99) | int(99999) || NULL | NULL | NULL | string(1)"d" | string(1)"c" | int(99) | int(99999) || || 4. $x = array_pop((array_slice($array, -1, 1))); || NULL | NULL | NULL | string(1)"d" | string(1)"c" | int(99) | int(99999) || NULL | NULL | NULL | string(1)"d" | string(1)"c" | int(99) | int(99999) || NULL | NULL | NULL | string(1)"d" | string(1)"c" | int(99) | int(99999) || || 5. $x = end($array); reset($array); || NULL | bool(false) | NULL | string(1)"d" | string(1)"c" | int(99) | int(99999) || NULL | bool(false) | NULL | string(1)"d" | string(1)"c" | int(99) | int(99999) || NULL | bool(false) | NULL | string(1)"d" | string(1)"c" | int(99) | int(99999) || || 6. $x = end((array_values($array))); || NULL | bool(false) | NULL | string(1)"d" | string(1)"c" | int(99) | int(99999) || NULL | bool(false) | NULL | string(1)"d" | string(1)"c" | int(99) | int(99999) || NULL | bool(false) | NULL | string(1)"d" | string(1)"c" | int(99) | int(99999) || || 7. $x = $array[count($array)-1]; || NULL | NULL | NULL | string(1)"d" | string(1)"b" | int(99) | int(99999) || NULL | NULL | NULL | string(1)"d" | string(1)"b" | int(99) | int(99999) || NULL | NULL | NULL | string(1)"d" | string(1)"b" | int(99) | int(99999) || || 8. $keys = array_keys($array); $x = $array[$keys[count($keys)-1]]; || NULL | NULL | NULL | string(1)"d" | string(1)"c" | int(99) | int(99999) || NULL | NULL | NULL | string(1)"d" | string(1)"c" | int(99) | int(99999) || NULL | NULL | NULL | string(1)"d" | string(1)"c" | int(99) | int(99999) || || 9. $x = $array[] = array_pop($array); || NULL | NULL | NULL | string(1)"d" | string(1)"c" | int(99) | int(99999) || NULL | NULL | NULL | string(1)"d" | string(1)"c" | int(99) | int(99999) || NULL | NULL | NULL | string(1)"d" | string(1)"c" | int(99) | int(99999) || || 10. $x = $array[array_key_last($array)]; || N/A | N/A | N/A | N/A | N/A | N/A | N/A || N/A | N/A | N/A | N/A | N/A | N/A | N/A || N/A | N/A | N/A | N/A | N/A | N/A | N/A || ||=================OPTIONS - FEMTOSECONDS PER ITERATION=================++===============+===============+===============+===============+===============+===============+===============++===============+===============+===============+===============+===============+===============+===============++===============+===============+===============+===============+===============+===============+===============<| || 1. $x = array_values(array_slice($array, -1))[0]; || 803 | 466 | 390 | 384 | 373 | 764 | 1.046.642 || 691 | 252 | 101 | 128 | 93 | 170 | 89.028 || 695 | 235 | 90 | 97 | 95 | 188 | 87.991 || || 2. $x = array_slice($array, -1)[0]; || 414 | 349 | 252 | 248 | 246 | 604 | 1.038.074 || 373 | 249 | 85 | 91 | 90 | 164 | 90.750 || 367 | 224 | 78 | 85 | 80 | 155 | 86.141 || || 3. $x = array_pop((array_slice($array, -1))); || 724 | 228 | 323 | 318 | 350 | 673 | 1.042.263 || 988 | 285 | 309 | 317 | 331 | 401 | 88.363 || 877 | 266 | 298 | 300 | 326 | 403 | 87.279 || || 4. $x = array_pop((array_slice($array, -1, 1))); || 734 | 266 | 358 | 356 | 349 | 699 | 1.050.101 || 887 | 288 | 316 | 322 | 314 | 408 | 88.402 || 935 | 268 | 335 | 315 | 313 | 403 | 86.445 || || 5. $x = end($array); reset($array); || 715 | 186 | 185 | 180 | 176 | 185 | 172 || 674 | 73 | 69 | 70 | 66 | 65 | 70 || 693 | 65 | 85 | 74 | 68 | 70 | 69 || || 6. $x = end((array_values($array))); || 877 | 205 | 320 | 337 | 304 | 2.901 | 7.921.860 || 948 | 300 | 336 | 308 | 309 | 509 | 29.696.951 || 946 | 262 | 301 | 309 | 302 | 499 | 29.234.928 || || 7. $x = $array[count($array)-1]; || 123 | 300 | 137 | 139 | 143 | 140 | 144 || 312 | 218 | 48 | 53 | 45 | 47 | 51 || 296 | 217 | 46 | 44 | 53 | 53 | 55 || || 8. $keys = array_keys($array); $x = $array[$keys[count($keys)-1]]; || 494 | 593 | 418 | 435 | 399 | 3.873 | 12.199.450 || 665 | 407 | 103 | 109 | 114 | 431 | 30.053.730 || 647 | 445 | 91 | 95 | 96 | 419 | 30.718.586 || || 9. $x = $array[] = array_pop($array); || 186 | 178 | 175 | 188 | 180 | 181 | 186 || 83 | 78 | 75 | 71 | 74 | 69 | 83 || 71 | 64 | 70 | 64 | 68 | 69 | 81 || || 10. $x = $array[array_key_last($array)]; || N/A | N/A | N/A | N/A | N/A | N/A | N/A || N/A | N/A | N/A | N/A | N/A | N/A | N/A || 370 | 223 | 49 | 52 | 61 | 57 | 52 || \=========================================================================================================================================================================================================================================================================================================================================================================================================================/ |
上述致命、警告和通知代码翻译为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | F1 = Fatal error: Call to undefined function array_key_last() in Command line code on line 1 F2 = Fatal error: Uncaught Error: Call to undefined function array_key_last() in Command line code:1 W1 = Warning: array_slice() expects parameter 1 to be array, null given in Command line code on line 1 W2 = Warning: array_values() expects parameter 1 to be array, null given in Command line code on line 1 W3 = Warning: array_pop() expects parameter 1 to be array, null given in Command line code on line 1 W4 = Warning: end() expects parameter 1 to be array, null given in Command line code on line 1 W5 = Warning: reset() expects parameter 1 to be array, null given in Command line code on line 1 W6 = Warning: array_keys() expects parameter 1 to be array, null given in Command line code on line 1 W7 = Warning: count(): Parameter must be an array or an object that implements Countable in Command line code on line 1 W8 = Warning: array_key_last() expects parameter 1 to be array, null given in Command line code on line 1 N1 = Notice: Undefined offset: 0 in Command line code on line 1 N2 = Notice: Only variables should be passed by reference in Command line code on line 1 N3 = Notice: Undefined offset: -1 in Command line code on line 1 N4 = Notice: Undefined index: in Command line code on line 1 |
基于此输出,我得出以下结论:
- 较新版本的PHP性能更好,但这些选项的速度明显变慢:
- 选项6。
$x = end((array_values($array))); - 选项8。
$keys = array_keys($array); $x = $array[$keys[count($keys)-1]];
- 选项6。
- 这些选项最适合大型阵列:
- 选项5。
$x = end($array); reset($array); - 选项7。
$x = $array[count($array)-1]; - 选项9。
$x = $array[] = array_pop($array); - 选项10。
$x = $array[array_key_last($array)]; (从php 7.3开始)
- 选项5。
- 这些选项只能用于自动索引数组:
- 选项7。
$x = $array[count($array)-1]; (由于count 的使用) - 选项9。
$x = $array[] = array_pop($array); (因赋值丢失原键)
- 选项7。
- 此选项不保留数组的内部指针
- 选项5。
$x = end($array); reset($array);
- 选项5。
- 此选项试图修改选项.5。保留数组的内部指针(但遗憾的是,对于非常大的数组,它的伸缩性不好)
- 选项6。
$x = end((array_values($array)));
- 选项6。
- 新的
array_key_last 函数似乎没有上述任何限制,但在撰写本文时仍然是一个rc(因此使用rc或等待其2018年12月发布):- 选项10。
$x = $array[array_key_last($array)]; (从php 7.3开始)
- 选项10。
根据将数组用作堆栈还是队列,您可以对选项9进行更改。
避免传递引用错误(例如"end(array_values($foo))"的一种方法是使用call_user_func或call_user_func_array:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // PHP Fatal error: Only variables can be passed by reference // No output (500 server error) var_dump(end(array(1, 2, 3))); // No errors, but modifies the array's internal pointer // Outputs"int(3)" var_dump(call_user_func('end', array(1, 2, 3))); // PHP Strict standards: Only variables should be passed by reference // Outputs"int(3)" var_dump(end(array_values(array(1, 2, 3)))); // No errors, doesn't change the array // Outputs"int(3)" var_dump(call_user_func('end', array_values(array(1, 2, 3)))); |
未经测试的:这不管用吗?
1 2 3 |
由于数组_值返回的数组是短暂的,没有人关心它的指针是否被重置。
如果你需要钥匙,我想你会的:
1 2 3 |
如果您不关心修改内部指针(同时支持索引和关联数组):
1 2 3 4 5 |
如果需要一个不修改内部指针的实用函数(因为数组是按值传递的,并且函数对其副本进行操作):
请注意,PHP"即时"生成副本,即仅在实际需要时才生成副本。
因此,下面的替代方法实际上更快,因为它不会在内部复制数组,只会生成一个切片:
1 2 3 4 5 6 7 8 | function array_last($array) { if (empty($array)) { return null; } foreach (array_slice($array, -1) as $value) { return $value; } } |
这个"foreach/return"是一个有效获取第一个(这里是单个)项目的调整。
最后,最快的替代方案,但仅限于索引数组:
对于记录,这里是我的另一个答案,关于数组的第一个元素。
我经常需要这样做来处理堆栈,我总是感到困惑,没有一个本机函数可以在不以某种形式操纵数组或其内部指针的情况下完成它。
所以我通常携带一个在关联数组上也可以安全使用的util函数。
1 2 3 4 5 6 7 | function array_last($array) { if (count($array) < 1) return null; $keys = array_keys($array); return $array[$keys[sizeof($keys) - 1]]; } |
end()将提供数组的最后一个元素
1 2 3 4 5 |
要获取数组的最后一个元素,请使用:
1 |
基准
我重复了1000次,获取了分别包含100和50000个元素的大数组和小数组的最后一个元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | Method: $array[count($array)-1]; Small array (s): 0.000319957733154 Large array (s): 0.000526905059814 Note: Fastest! count() must access an internal length property. Note: This method only works if the array is naturally-keyed (0, 1, 2, ...). Method: array_slice($array, -1)[0]; Small array (s): 0.00145292282104 Large array (s): 0.499367952347 Method: array_pop((array_slice($array, -1, 1))); Small array (s): 0.00162816047668 Large array (s): 0.513121843338 Method: end($array); Small array (s): 0.0028350353241 Large array (s): 4.81077480316 Note: Slowest... |
我使用了5.5.32版本的PHP。
从php 7.3版开始,引入了
由于PHP中的数组不是严格的数组类型,即从索引0开始的固定大小字段的固定大小集合,而是动态扩展的关联数组,因此处理具有未知键的位置非常困难,解决方法的性能也不太好。相反,实数数组将通过指针算术很快地在内部进行寻址,最后一个索引在编译时就已经通过声明被知道了。
从7.3版开始,内置函数至少解决了第一个和最后一个位置的问题。这甚至可以在不显示任何数组文本警告的情况下工作:
1 2 | $first = array_key_first( [1, 2, 'A'=>65, 'B'=>66, 3, 4 ] ); $last = array_key_last ( [1, 2, 'A'=>65, 'B'=>66, 3, 4 ] ); |
显然,最后一个值是:
1 | $array[array_key_last($array)]; |
1 |
未对$array指针进行任何修改。这避免了
1 |
在某些情况下可能不需要。
为了我:
1 |
具有关联:
1 |
要做到这一点并避免e_严格,并且不要弄乱数组的内部指针,可以使用:
1 2 3 |
lelement只能与副本一起使用,因此它不会影响数组的指针。
使用end()函数。
1 2 |
注:对于(php 7>=7.3.0)我们可以使用array_key_last-获取数组的最后一个键
1 |
参考:http://php.net/manual/en/function.array-key-last.php
怎么样:
1 |
- 适用于关联数组
- 当
$array == [] 时工作(返回false ) - 不影响原始数组
另一个解决方案:
1 2 3 | $array = array('a' => 'a', 'b' => 'b', 'c' => 'c'); $lastItem = $array[(array_keys($array)[(count($array)-1)])]; echo $lastItem; |
还有一个可能的解决方案…
1 |
现在,我更喜欢一直使用这个助手,正如php.net/end答案中所建议的那样。
1 2 3 4 5 6 7 8 9 |
这将始终保持指针的原样,并且我们将不必担心括号、严格的标准或其他任何问题。
从数组中获取最后一个值:
1 |
用于删除最后一个值窗体数组:
1 |
简单地说:
不会重置数组,也不会给出严格警告。
另外,因为投票最多的答案仍然没有双括号,所以我提交了这个答案。
我认为这是对所有现有答案的轻微改进:
1 |
- 性能优于
end() 或使用array_keys() 的解决方案,特别是对于大型阵列 - 不会修改数组的内部指针
- 不会尝试访问空数组的未定义偏移量
- 对于空数组、索引数组、混合数组和关联数组,将按预期工作
上面的答案很好,但是正如@paul van leeuwen和@quasimodos clone所提到的,php 7.3将引入两个新的函数来直接解决这个问题-array_key_first()和array_key_last()。
现在,您可以使用以下polyfill(或shim)函数开始使用此语法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | // Polyfill for array_key_last() available from PHP 7.3 if (!function_exists('array_key_last')) { function array_key_last($array) { return array_slice(array_keys($array),-1)[0]; } } // Polyfill for array_key_first() available from PHP 7.3 if (!function_exists('array_key_first')) { function array_key_first($array) { return array_slice(array_keys($array),0)[0]; } } // Usage examples: $first_element_key = array_key_first($array); $first_element_value = $array[array_key_first($array)]; $last_element_key = array_key_last($array); $last_element_value = $array[array_key_last($array)]; |
警告:这需要php 5.4或更高版本。
1 2 3 4 5 6 7 8 9 10 11 |
从php 7.3开始,这是可用的
$lastel=$myarray[数组键最后($myarray[))
如果您想在数组的循环中获取数组的最后一个元素,该怎么办?
下面的代码将导致无限循环:
1 2 3 4 5 6 7 |
对于非关联数组,解决方案显然很简单:
1 2 3 4 5 6 | $last_element = $array[sizeof ($array) - 1]; foreach ($array as $key => $item) { if ($last_element == $item) { // something useful here } } |
在几乎每种带有数组的语言中,您都不能真正地使用[A.SIZE-1]出错。我想不出一个具有1个基数组(而不是零基数组)的语言示例。