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 协议》,转载必须注明作者和本文链接
只不过是一粒尘埃罢了
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 6

这个问题不奇怪

$arr[2] = 2;
$arr[1] = 1;
$arr[0] = 0;

foreach ($arr as $k => $v){
      echo 'k'.$k.' v'.$v. PHP_EOL;
}

如果你把 foreach 里面的 k 也打印出来 会发现遍历顺序是按照数组元素的添加顺序在遍历,也就是说,PHP的底层数组,并不会去帮你做排序,只会按照添加顺序来添加元素,这很合理。

2年前 评论

这个问题不奇怪

$arr[2] = 2;
$arr[1] = 1;
$arr[0] = 0;

foreach ($arr as $k => $v){
      echo 'k'.$k.' v'.$v. PHP_EOL;
}

如果你把 foreach 里面的 k 也打印出来 会发现遍历顺序是按照数组元素的添加顺序在遍历,也就是说,PHP的底层数组,并不会去帮你做排序,只会按照添加顺序来添加元素,这很合理。

2年前 评论

如果提前声明数组的容量,就可以按你预想的展示来。

未声明就进行使用的话,应该要按顺序入的链表,不然万一你声明了一个很大的key,是不是要预分配很大的一份空间出来或者需要对新增数据需要进行频繁的插入和移位(可能有些场景你也不想这样做),这样更容易造成问题。 从这个角度来分析的话,这个设计是没有问题的。

2年前 评论

@Rekkles 或许foreach就是这样设计的。

2年前 评论

@小李世界 for的输出顺序很合理啊,因为索引通过变量【i】来固定了,输出肯定是排序后的

2年前 评论
小李世界 2年前

当你对它附加key的时候,即使你为它附加了一个数字key,让它表面看起来像索引数组,但其实它是一个关联数组。对于关联数组,如果你一定要用for去遍历它,那么你可以通过指针来操作:

$length = count($arr);
for ($i = 0; $i < $length; $i++) {
    echo current($arr) . '  ';
    next($arr);
}
reset($arr);
2年前 评论
fatrbaby

所以说PHP的数组是一个伪装成数组的Map :joy:

2年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!