数组
1.初识数组
在PHP中,数组是由一个或多个数组元素组成的,每个数组元素由键(Key)和值(Value)构成。其中,“键”为元素的识别名称,也被称为数组下标;“值”为元素的内容;“键”和“值”之间存在一种对应关系,称之为映射。
在PHP中,根据键的数据类型,可以将数组划分为索引数组和关联数组,具体如下。
1.索引数组
索引数组是指键名为整数的数组。默认情况下,索引数组的键名是从0开始,并依次递增。它主要适用于利用位置(0、1、2……)来标识数组元素的情况。如图4-1所示。另外,索引数组的键名也可以自己指定。

2.关联数组
关联数组是指键名为字符串的数组。通常情况下,关联数组元素的“键”和“值”之间有一定的业务逻辑关系。因此,通常使用关联数组存储一系列具有逻辑关系的变量。

PHP中的数组还可以根据维数划分为一维数组、二维数组、三维数组等。
2.数组的基本使用
1.数组的定义
1.array()语言结构方式
1.定义索引数组
array()语言结构中的数组元素使用“键=>值”的方式进行表示,各元素之间使用逗号进行分隔。
$fruits = array('apple','grape','pear'); //省略键名$sports = array(2 =>'baskatball',4 =>'football'); //指定键名
2.定义关联数组
$info = array('id' => 10,'name' => 'Tom','tel' => 13248400911);
在定义关联数组时,“值”可以是任意类型数据,而“键”则有明确的数据类型要求,具体如下。
- 键只能是整型或字符串型的数据,如果是其他类型,则会执行类型自动转换。
- 合法整型的字符串会被转为整型,如“2”转为2,而“02”则不会被转换。
- 浮点数会被舍去小数部分直接转换成整型,如“2.6”转为2。
- 布尔类型的true会被转为1,false转为0。
- NULL类型会被转为空字符串。
- 若数组中存在相同键名的元素时,后面的元素会覆盖前面元素的值。
3.定义混合数组
$temp = array();$mixed = array(2,'str','id' =>5,5 =>'b','a');
上述示例定义了一个空数组mixed。其中,$mixed数组的元素“b”指定了数字键名为“5”,则其后的“a”元素会自动将前面最大的数字键名加1后,作为其键名,即5+1得到键名6。
4.定义多维数组
只需将数组元素设置为数组即可。下面定义一个二维数组进行演示,如下所示。
<?php$data = array(0 => array('name' => 'Tom','gender' => '男'),1 => array('name' => 'Lucy','gender' => '女'),2 => array('name' => 'Jimmy','gender' => '男'),);?>
2.赋值方式
使用赋值方式定义数组就是创建一个数组变量,然后使用赋值运算符直接给变量赋值。具体示例如下。
$arr[] = 123; //存出结果:$arr[0] = 123$arr[] = 'hello'; //存出结果:$arr[1] = 'hello'$arr[4] = 'php'; //存出结果:$arr[4] = 'php'$arr['name'] = 'Tom'; //存出结果:$arr['name'] = 'Tom'$arr[] ='Java'; //存出结果:$arr[5] = 'Java'
3.短数组定义法([ ])
短数组定义法([])与array()语法结构的使用方式相同,只需将array()替换为[]即可,示例如下。
$weather = ['wind','fine']; //相当于array('wind','fine')$num = [[1,3],[2,4]]; //相当于array(array(1,3),array(2,4))
2.访问数组
数组定义完成后,若想要查看数组中某个具体的元素,则可以通过“数组名[键]”的方式获取。使用示例如下。
$sub =['PHP','JAVA','C++','Python'];echo $sub[1]; //输出:JAVAecho $sub[3]; //输出:Python
另外,若要一次查看数组中的所有元素,则可以利用前面学习过的输出语句函数print_r()和var_dump(),通常情况下为了使输出的函数按照一定的格式打印,查看时经常与pre标记一起使用。
echo '<pre>';print_r($sub);echo '<pre>';var_dump($sub);
print_r打印结果:
Array([0] => PHP[1] => JAVA[2] => C++[3] => Python)
var_dump打印结果:
array(4) {[0]=>string(3) "PHP"[1]=>string(4) "JAVA"[2]=>string(3) "C++"[3]=>string(6) "Python"}
3.遍历数组
所谓遍历数组就是一次访问数组中所有元素的操作。通常情况下,使用foreach()语句完成数组的遍历,具体使用示例如下。
$info = array('id' => 10,'name' => 'Tom','tel' => 13248400911);//使用方式一foreach ($info as $k => $v){echo $k.':'.$v.''; //输出结果:id:10name:Tomtel:13248400911}//使用方式二foreach ($info as $v){echo $v.''; //输出结果:10Tom13248400911}
从示例可知,foreach()的第1个参数表示待遍历的数组变量名称,as关键字后指定的是数组元素,v表示元素的“值”,“键”和“值”之间使用“=>”连接。然后在“{}”中可以完成元素的操作。例如,上述示例中对每个遍历的元素利用echo输出。其中,
v的变量名可以根据实际情况随意设置,如
value等;
当不需要遍历数组元素的键名时,可以在as关键字后直接设置一个变量表示当前元素的值,如“使用方式二”中设置的$v。
4.数组的删除
可以使用PHP提供的unset()函数完成数据的删除。
<?php$userinfo = [1 => ['name' => 'tom','sex' => 'boy','age' => 18],2 => ['name' => 'lucy','sex' => 'girl','age' => 17],3 => ['name' => 'lilei','sex' => 'boy','age' => 18],4 => ['name' => 'hanmeimei','sex' => 'girl','age' => 19]];unset($userinfo[2]);echo '<pre>';print_r($userinfo);echo '<pre>';?>
第8行代码利用unset()函数删除了$data数组中键名为2的元素。数组元素被删除后,数组中的数字键名不会自动填补空缺的数字。
unset()函数除了可以删除指定键名的元素,还可以删除整个数组.
5.数组操作符
常见的数组操作运算符如下所示。

上图列举了一些常用的数组操作符。其中,“+”为联合运算符,用于合并数组,如果出现下标相同的元素,则保留第1个数组内的元素,具体使用示例如下所示。
<?php$num = [2,4];$alp = ['a','b','c','d'];$mer1 = $num + $alp;$mer2 = $alp +$num;print_r($mer1); //输出:Array ( [0] => 2 [1] => 4 [2] => c [3] => d )print_r($mer2); //输出Array ( [0] => a [1] => b [2] => c [3] => d )?>
从上述示例可以看出,当数组alp的键名相同时,保留了运算符“+”左边数组内的元素,操作符右边数组内的元素会被覆盖。
3.数组查找
PHP中数组类型的变量可以保存任意多个数据,而开发中经常需要在数组中查找到指定的数据进行对应的操作。这种查找数据的方法最常用的有顺序查找法和二分查找法。
1 .顺序查找法
顺序查找法是最简单的查找法,只需按照数组中元素的保存顺序,利用待查的值与数组中的元素从前往后一个一个地进行比较,直到找到目标值或查找失败。

顺序查找法对数组中元素大小的排序无要求,这使得它的适应性比较高,但由于其每次查找都需要遍历一次数组,因此效率较低。
<?phpfunction search($arr,$find){foreach ($arr as $k => $v){if($find == $v){return "{$find}在数组中的键名为:$k";}}return "查找失败";}$arr = [11,22,33,44,55];echo search($arr,44); //输出:44在数组中的键名为:3echo '<br>';echo search($arr,66); //输出:查找失败?>
2.二分查找法
二分查找法是针对有序数组的一种查找法,它的查询效率非常高。具体实现原理是,每次将查找值与数组中间位置元素的值进行比较,相等返回;不等则排除掉数组中一半的元素,然后根据比较结果大或小,再与数组中剩余一半中间位置元素的值进行比较,以此类推,直到找到目标值或查找失败。
<?phpfunction bSearch($arr,$start,$len,$find){$end = $len -1;$mid = round($len / 2);if ($start > $end){return '查找失败';}elseif ($arr[$mid] > $find){return bSearch($arr,$start,$mid - 1,$find);}elseif ($arr[$mid] < $find){return bSearch($arr,$start,$mid + 1,$find);}else {return $mid;}}$arr = [1,5,9,15,28,46,98];$len = count($arr);echo bSearch($arr,0,$len,28);echo bSearch($arr,0,$len,10);?>
上述代码中,bSearch()函数的参数依次表示为从小到大排序的数组、查找数组的开始键名、数组长度和待查找的值。第4行代码用于计算给定数组的结尾键名,第5行用于计算数组里中间元素的键名,并对小数的情况进行四舍五入。
第6行代码用于判断当开始与结尾键名不合法时,返回查找失败的提示信息;第8行用于判断中间元素的值大于查找值时,递归调用bSearch()函数,修改结尾键名。第10行用于判断中间元素的值小于查找值时,递归调用bSearch()函数,修改开始键名。第13行用于查找成功时,返回对应的键名。

4.数组排序
1.冒泡排序
冒泡排序是计算机科学领域中较简单的排序算法。在冒泡排序的过程中,按照要求从小到大排序或从大到小排序,不断比较数组中相邻两个元素的值,较小或较大的元素前移。具体排序过程如图下图所示。从图中可以看出,冒泡排序比较的轮数是数组长度减1,每轮比较的对数等于数组的长度减当前的轮数。

<?phpfunction bubbleSort($arr){//外层循环控制需要比较的轮数for ($i = 1,$len = count($arr);$i < $len; ++$i) {for ($j = 0; $j < $len - $i; ++$j) { //内层循环控制参与比较的元素if ($arr[$j] > $arr[$j + 1]) { //比较相邻的两个元素$temp = $arr[$j];$arr[$j] = $arr[$j + 1];$arr[$j + 1] = $temp;}}}return $arr;}$arr = [10,2,5,27,98,31];print_r(bubbleSort($arr)); //输出:Array ( [0] => 2 [1] => 5 [2] => 10 [3] => 27 [4] => 31 [5] => 98 )?>
上述第5行代码用于循环冒泡排序的轮数,第6~12行代码用于循环比较数组中两个相邻的元素,如果当前元素大于后一个元素时,则通过第8~10行代码交换两个元素的值。编写完成后,调用函数bubbleSort(),将数组按照从小到大的顺序进行排序。
需要注意的是,冒泡排序的效率很低,在实际中使用较少。
2.简单选择排序
简单选择排序是一种非常直观的排序算法。它的实现原理是,从待排序的数组中选出最小或最大的一个元素与数组的第1个元素互换,接着再在剩余的数组元素中选择最小的一个与数组的第2个元素互换,依次类推,直到全部待排序的数组元素排序完成。如按照从小到大的顺序完成简单选择排序,具体实现如图所示。其中,图中利用箭头标注的两个元素就是在此次循环中互换的元素。

<?phpfunction selectSort($arr){for ($i = 0,$len = count($arr);$i < $len - 1;++$i){for ($j = $i + 1;$j < $len;++$j){if ($arr[$j] < $arr[$i]){$temp = $arr[$i];$arr[$i] = $arr[$j];$arr[$j] = $temp;}}}return $arr;}$arr = [9,1,2,10,4,12];print_r(selectSort($arr)); //输出:Array ( [0] => 1 [1] => 2 [2] => 4 [3] => 9 [4] => 10 [5] => 12 )?>
在上述示例中,第4行用于循环遍历待排序数组,第5~11行代码用于循环遍历当前元素后所有的元素,并一一与其进行比较,只要小于当前元素就进行互换,直到选出最小的元素,依次类推,完成所有元素的排序。
值得一提的是,选择排序是不稳定的排序方法,在实际应用中使用也比较少。
3.快速排序
快速排序是对冒泡排序的一种优化。它的实现思路是,首先选择一个基准元素,通常选择待排序数组的第1个数组元素。通过一趟排序,将要排序的数组分成两个部分,其中一部分比基准元素小,另一部分比基准元素大,然后再利用同样的方法递归地排序划分出的两部分,直到将所有划分的数组排序完成.

<?phpfunction quickSort($arr){//获取待排序数组长度,当小于或等于1时直接返回数组(递归出口)$len = count($arr);if($len <= 1){return $arr;}//设置基准元素$pivot = $arr[0];$small = $big = [];//根据基准元素,将数组分成2个部分:小于和大于for ($i = 1;$i < $len;++$i){if ($arr[$i] < $pivot) { //小于基准元素$small[] = $arr[$i];}else { //大于等于基准元素$big[] = $arr[$i];}}//分别采取相同方案递归排序小于、大于部分的数组,然后进行合并return array_merge(quickSort($small),[$pivot],quickSort($big));}$arr = [31,98,5,27,2,78];print_r(quickSort($arr)); //输出:Array ( [0] => 2 [1] => 5 [2] => 27 [3] => 31 [4] => 78 [5] => 98 )?>
在上述代码中,quickSort()函数传递的arr分为小于基准和大于等于基准元素两部分,第21行代码用于分别递归调用quickSort()处理小于和大于基准元素的排列,然后使用PHP提供的内置数组函数array_merge()完成排序后数组元素的合并。
4.插入排序
插入排序也是冒泡排序的优化,是一种直观的简单排序算法。它的实现原理是,通过构建有序数组元素的存储,对未排序数组的元素,在已排序的数组中从最后一个元素向第一个元素遍历,找到相应位置并插入。其中,待排序数组的第1个元素会被看作是一个有序的数组,从第2个至最后一个元素会被看作是一个无序数组。如按照从小到大的顺序完成插入排序,具体实现如图4-9所示。

从图中可以看出,插入排序比较的次数与无序数组的长度相等,每次无序数组元素与有序数组中的所有元素进行比较,比较后找到对应位置插入,最后即可得到一个有序的数组。
<?phpfunction insertSort($arr){for ($i = 1,$len = count($arr);$i < $len; ++$i){ //遍历无序数组for ($j = $i;$j > 0; --$j) { //遍历有序数组if ($arr[$j] < $arr[$j -1]) { //无序与有序进行比较$temp = $arr[$j];$arr[$j] = $arr[$j - 1];$arr[$j - 1] = $temp;}}}return $arr;}$arr = [98,7,65,54,12,6];print_r(insertSort($arr)); //输出:Array ( [0] => 6 [1] => 7 [2] => 12 [3] => 54 [4] => 65 [5] => 98 )?>
在上述示例中,假设用户传递进来的数组arr中剩余的元素为无序数组。然后通过第4~12行代码进行循环。其中,第5~11行代码用于无序数组元素与有序数组中的所有元素进行比较,若无序元素
j]小于有序数组中的元素,则进行插入。最后通过第13行代码将排序后的数组返回。
5.数组的常用函数
1.指针操作函数
| 函数名称 | 功能描述 |
|---|---|
| current() | 获取数组中当前指针指向元素的值 |
| key() | 获取数组中当前指针指向的元素的键 |
| next() | 将数组中的内部指针向前移一位 |
| prev() | 将数组中的内部指针倒回一位 |
| each() | 获取数组中当前的键值对并将数组指针向前移动一步 |
| end() | 将数组中的内部指针指向最后一个元素 |
| reset() | 将数组中的内部指针指向最后一个元素 |
1.通过指针函数访问数组
<?php$arr = ['a','b','c','d','e'];echo key($arr).'--'.current($arr); //输出:0--aecho next($arr); //输出:becho end($arr); //输出:eecho prev($arr); //输出:decho reset($arr); //输出:a?>
2.通过each()函数访问数组
each()函数可以获取数组中当前元素的键和值,并以数组形式返回,具体如下。
<?php$arr = ['sub'=>'PHP'];echo '<pre>';print_r(each($arr));echo '<pre>';?>
输出结果:
The each() function is deprecated.Array([1] => PHP[value] => PHP[0] => sub[key] => sub)
2.数组元素操作函数
在操作数组过程中,经常会遇到在数组的前面或后面添加或删除元素的情况。为此,PHP提供了几个入栈和出栈的函数.
| 函数名称 | 功能描述 |
|---|---|
| array_pop() | 将数组最后一个元素弹出(出栈) |
| array_push() | 将一个或多个元素压入数组的末尾(入栈) |
| array_unshift() | 在数组开头插入一个或多个元素 |
| array_shift() | 将数组开头的元素移出数组 |
| array_unique() | 移出数组中重复的值 |
| array_slice() | 从数组中截取部分数组 |
| array_splice() | 将数组中的一部分元素去掉并用其他值取代 |
<?php$arr = ['a','b'];array_pop($arr); //输出:Array ( [0] => a )print_r($arr);array_push($arr,'c'); //输出:Array ( [0] => a [1] => c )print_r($arr);array_unshift($arr,'d','e'); //输出:Array ( [0] => d [1] => e [2] => a [3] => c )print_r($arr);array_shift($arr); //输出:Array ( [0] => e [1] => a [2] => c )print_r($arr);?>
从上述代码可以看出,array_shift()和array_unshift()函数对于元素的数字键名会重新进行分配。
3.排序函数
PHP还提供了内置的数组排序函数,可以轻松对数组实现排序、逆向排序、按键名排序等操作。
| 函数名称 | 功能描述 |
|---|---|
| sort() | 对数组排序(从低到高) |
| rsort() | 对数组排序(从高到低) |
| asort() | 对数字进行排序并保持键值关系 |
| ksort() | 对数组按照键名排序 |
| arsort() | 对数组进行逆向排序并保持键值关系 |
| krsort() | 对数组按照键名逆向排序 |
| shuffle() | 将数组元素顺序打乱 |
| array_multisort() | 对多个数组或多维数组进行排序 |
<?php$arr = ['a','c','b'];sort($arr);print_r($arr); //输出:Array ( [0] => a [1] => b [2] => c )rsort($arr);print_r($arr); //输出:Array ( [0] => c [1] => b [2] => a )asort($arr);print_r($arr); //输出:Array ( [2] => a [1] => b [0] => c )arsort($arr);print_r($arr); //输出:Array ( [0] => c [1] => b [2] => a )krsort($arr);print_r($arr); //输出:Array ( [2] => a [1] => b [0] => c )?>
4.检索函数
| 函数名称 | 功能描述 |
|---|---|
| in_array() | 检查数组中是否存在某个值 |
| array_search() | 在数组中搜索给定的值,如果成功则返回相应的键名 |
| array_key_exists() | 检查给定的键名是否存在与数组中 |
<?php$arr = ['a'=>1,'b'=>2,'c'=>3];var_dump(in_array(2,$arr)); //输出:bool(true)var_dump(array_search(2,$arr)); //输出:string(1) "b"var_dump(array_key_exists(2,$arr)); //输出:bool(false)?>
5.其他数组函数
PHP还提供了很多其他常用的数组函数,具体可参考PHP手册。
| 函数名称 | 功能描述 |
|---|---|
| count() | 计算数组中的元素数目或对象中的属性个数 |
| range() | 建立一个包含指定范围元素的数组 |
<?php$arr = ['a'=>1,'b'=>2,'c'=>3];print_r(count($arr)); //输出:3$arr2 = range(1,5);print_r($arr2); //输出:Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 )?>
