php 数组遍历奇怪现象
<?php
$arr[2] = 'maxiao';
$arr[1] = 2015;
$arr[0] = 2014;
foreach ($arr as $key => $val) {
echo $val . ' ';
}
使用foreach遍历,结果是:
maxiao 2015 2014
$length = count($arr);
for($i = 0;$i < $length;$i++) {
echo $arr[$i] . ' ';
}
使用for遍历,结果是:
2014 2015 maxiao
啊这。。foreach为什么不是按索引来遍历?而是按照添加元素的时间来遍历的。
这涉及到来php数组的底层实现,简单来说,php数据底层是一个hashtable(用链表的方式来解决hash冲突)+ 双向链表进行组织的数据,而采用foreach遍历数组的话,会根据链表来遍历,链表的顺序是添加元素的顺序。而如果用for来遍历数组的话,使用的是hashtable来查找元素。所以顺序是索引的顺序。大佬的讲解:
https://www.laruence.com/2009/08/23/1065.html。
ps:本来想画个结构图的,太麻烦了,略。
本作品采用《CC 协议》,转载必须注明作者和本文链接
高认可度评论:
这个问题不奇怪
如果你把 foreach 里面的 k 也打印出来 会发现遍历顺序是按照数组元素的添加顺序在遍历,也就是说,PHP的底层数组,并不会去帮你做排序,只会按照添加顺序来添加元素,这很合理。
这个问题不奇怪
如果你把 foreach 里面的 k 也打印出来 会发现遍历顺序是按照数组元素的添加顺序在遍历,也就是说,PHP的底层数组,并不会去帮你做排序,只会按照添加顺序来添加元素,这很合理。
@Rekkles 或许foreach就是这样设计的。
@小李世界 for的输出顺序很合理啊,因为索引通过变量【i】来固定了,输出肯定是排序后的
当你对它附加key的时候,即使你为它附加了一个数字key,让它表面看起来像索引数组,但其实它是一个关联数组。对于关联数组,如果你一定要用for去遍历它,那么你可以通过指针来操作:
所以说PHP的数组是一个伪装成数组的Map :joy:
如果提前声明数组的容量,就可以按你预想的展示来。
未声明就进行使用的话,应该要按顺序入的链表,不然万一你声明了一个很大的key,是不是要预分配很大的一份空间出来或者需要对新增数据需要进行频繁的插入和移位(可能有些场景你也不想这样做),这样更容易造成问题。 从这个角度来分析的话,这个设计是没有问题的。