数组

1.初识数组

在PHP中,数组是由一个或多个数组元素组成的,每个数组元素由键(Key)和值(Value)构成。其中,“键”为元素的识别名称,也被称为数组下标;“值”为元素的内容;“键”和“值”之间存在一种对应关系,称之为映射。

在PHP中,根据键的数据类型,可以将数组划分为索引数组和关联数组,具体如下。

1.索引数组

索引数组是指键名为整数的数组。默认情况下,索引数组的键名是从0开始,并依次递增。它主要适用于利用位置(0、1、2……)来标识数组元素的情况。如图4-1所示。另外,索引数组的键名也可以自己指定。

4.PHP数组 - 图1

2.关联数组

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

4.PHP数组 - 图2

PHP中的数组还可以根据维数划分为一维数组、二维数组、三维数组等。

2.数组的基本使用

1.数组的定义

1.array()语言结构方式

1.定义索引数组

array()语言结构中的数组元素使用“键=>值”的方式进行表示,各元素之间使用逗号进行分隔。

  1. $fruits = array('apple','grape','pear'); //省略键名
  2. $sports = array(2 =>'baskatball',4 =>'football'); //指定键名

2.定义关联数组
  1. $info = array('id' => 10,'name' => 'Tom','tel' => 13248400911);

在定义关联数组时,“值”可以是任意类型数据,而“键”则有明确的数据类型要求,具体如下。

  • 键只能是整型或字符串型的数据,如果是其他类型,则会执行类型自动转换。
  • 合法整型的字符串会被转为整型,如“2”转为2,而“02”则不会被转换。
  • 浮点数会被舍去小数部分直接转换成整型,如“2.6”转为2。
  • 布尔类型的true会被转为1,false转为0。
  • NULL类型会被转为空字符串。
  • 若数组中存在相同键名的元素时,后面的元素会覆盖前面元素的值。

3.定义混合数组
  1. $temp = array();
  2. $mixed = array(2,'str','id' =>5,5 =>'b','a');

上述示例定义了一个空数组4.PHP数组 - 图3mixed。其中,$mixed数组的元素“b”指定了数字键名为“5”,则其后的“a”元素会自动将前面最大的数字键名加1后,作为其键名,即5+1得到键名6。

4.定义多维数组

只需将数组元素设置为数组即可。下面定义一个二维数组进行演示,如下所示。

  1. <?php
  2. $data = array(
  3. 0 => array('name' => 'Tom','gender' => '男'),
  4. 1 => array('name' => 'Lucy','gender' => '女'),
  5. 2 => array('name' => 'Jimmy','gender' => '男'),
  6. );
  7. ?>

2.赋值方式

使用赋值方式定义数组就是创建一个数组变量,然后使用赋值运算符直接给变量赋值。具体示例如下。

  1. $arr[] = 123; //存出结果:$arr[0] = 123
  2. $arr[] = 'hello'; //存出结果:$arr[1] = 'hello'
  3. $arr[4] = 'php'; //存出结果:$arr[4] = 'php'
  4. $arr['name'] = 'Tom'; //存出结果:$arr['name'] = 'Tom'
  5. $arr[] ='Java'; //存出结果:$arr[5] = 'Java'

3.短数组定义法([ ])

短数组定义法([])与array()语法结构的使用方式相同,只需将array()替换为[]即可,示例如下。

  1. $weather = ['wind','fine']; //相当于array('wind','fine')
  2. $num = [[1,3],[2,4]]; //相当于array(array(1,3),array(2,4))

2.访问数组

数组定义完成后,若想要查看数组中某个具体的元素,则可以通过“数组名[键]”的方式获取。使用示例如下。

  1. $sub =['PHP','JAVA','C++','Python'];
  2. echo $sub[1]; //输出:JAVA
  3. echo $sub[3]; //输出:Python

另外,若要一次查看数组中的所有元素,则可以利用前面学习过的输出语句函数print_r()和var_dump(),通常情况下为了使输出的函数按照一定的格式打印,查看时经常与pre标记一起使用。

  1. echo '
  2. <pre>';
  3. print_r($sub);
  4. echo '
  5. <pre>';
  6. var_dump($sub);

print_r打印结果:

  1. Array
  2. (
  3. [0] => PHP
  4. [1] => JAVA
  5. [2] => C++
  6. [3] => Python
  7. )

var_dump打印结果:

  1. array(4) {
  2. [0]=>
  3. string(3) "PHP"
  4. [1]=>
  5. string(4) "JAVA"
  6. [2]=>
  7. string(3) "C++"
  8. [3]=>
  9. string(6) "Python"
  10. }

3.遍历数组

所谓遍历数组就是一次访问数组中所有元素的操作。通常情况下,使用foreach()语句完成数组的遍历,具体使用示例如下。

  1. $info = array('id' => 10,'name' => 'Tom','tel' => 13248400911);
  2. //使用方式一
  3. foreach ($info as $k => $v){
  4. echo $k.':'.$v.''; //输出结果:id:10name:Tomtel:13248400911
  5. }
  6. //使用方式二
  7. foreach ($info as $v){
  8. echo $v.''; //输出结果:10Tom13248400911
  9. }

从示例可知,foreach()的第1个参数表示待遍历的数组变量名称,as关键字后指定的是数组元素,4.PHP数组 - 图4v表示元素的“值”,“键”和“值”之间使用“=>”连接。然后在“{}”中可以完成元素的操作。例如,上述示例中对每个遍历的元素利用echo输出。其中,4.PHP数组 - 图5v的变量名可以根据实际情况随意设置,如4.PHP数组 - 图6value等;

当不需要遍历数组元素的键名时,可以在as关键字后直接设置一个变量表示当前元素的值,如“使用方式二”中设置的$v。

4.数组的删除

可以使用PHP提供的unset()函数完成数据的删除。

  1. <?php
  2. $userinfo = [
  3. 1 => ['name' => 'tom','sex' => 'boy','age' => 18],
  4. 2 => ['name' => 'lucy','sex' => 'girl','age' => 17],
  5. 3 => ['name' => 'lilei','sex' => 'boy','age' => 18],
  6. 4 => ['name' => 'hanmeimei','sex' => 'girl','age' => 19]
  7. ];
  8. unset($userinfo[2]);
  9. echo '
  10. <pre>';
  11. print_r($userinfo);
  12. echo '
  13. <pre>';
  14. ?>

第8行代码利用unset()函数删除了$data数组中键名为2的元素。数组元素被删除后,数组中的数字键名不会自动填补空缺的数字。

unset()函数除了可以删除指定键名的元素,还可以删除整个数组.

5.数组操作符

常见的数组操作运算符如下所示。

4.PHP数组 - 图7

上图列举了一些常用的数组操作符。其中,“+”为联合运算符,用于合并数组,如果出现下标相同的元素,则保留第1个数组内的元素,具体使用示例如下所示。

  1. <?php
  2. $num = [2,4];
  3. $alp = ['a','b','c','d'];
  4. $mer1 = $num + $alp;
  5. $mer2 = $alp +$num;
  6. print_r($mer1); //输出:Array ( [0] => 2 [1] => 4 [2] => c [3] => d )
  7. print_r($mer2); //输出Array ( [0] => a [1] => b [2] => c [3] => d )
  8. ?>

从上述示例可以看出,当数组4.PHP数组 - 图8alp的键名相同时,保留了运算符“+”左边数组内的元素,操作符右边数组内的元素会被覆盖。

3.数组查找

PHP中数组类型的变量可以保存任意多个数据,而开发中经常需要在数组中查找到指定的数据进行对应的操作。这种查找数据的方法最常用的有顺序查找法和二分查找法。

1 .顺序查找法

顺序查找法是最简单的查找法,只需按照数组中元素的保存顺序,利用待查的值与数组中的元素从前往后一个一个地进行比较,直到找到目标值或查找失败。

4.PHP数组 - 图9

顺序查找法对数组中元素大小的排序无要求,这使得它的适应性比较高,但由于其每次查找都需要遍历一次数组,因此效率较低。

  1. <?php
  2. function search($arr,$find)
  3. {
  4. foreach ($arr as $k => $v){
  5. if($find == $v){
  6. return "{$find}在数组中的键名为:$k";
  7. }
  8. }
  9. return "查找失败";
  10. }
  11. $arr = [11,22,33,44,55];
  12. echo search($arr,44); //输出:44在数组中的键名为:3
  13. echo '<br>';
  14. echo search($arr,66); //输出:查找失败
  15. ?>

2.二分查找法

二分查找法是针对有序数组的一种查找法,它的查询效率非常高。具体实现原理是,每次将查找值与数组中间位置元素的值进行比较,相等返回;不等则排除掉数组中一半的元素,然后根据比较结果大或小,再与数组中剩余一半中间位置元素的值进行比较,以此类推,直到找到目标值或查找失败。

  1. <?php
  2. function bSearch($arr,$start,$len,$find)
  3. {
  4. $end = $len -1;
  5. $mid = round($len / 2);
  6. if ($start > $end){
  7. return '查找失败';
  8. }elseif ($arr[$mid] > $find){
  9. return bSearch($arr,$start,$mid - 1,$find);
  10. }elseif ($arr[$mid] < $find){
  11. return bSearch($arr,$start,$mid + 1,$find);
  12. }else {
  13. return $mid;
  14. }
  15. }
  16. $arr = [1,5,9,15,28,46,98];
  17. $len = count($arr);
  18. echo bSearch($arr,0,$len,28);
  19. echo bSearch($arr,0,$len,10);
  20. ?>

上述代码中,bSearch()函数的参数依次表示为从小到大排序的数组、查找数组的开始键名、数组长度和待查找的值。第4行代码用于计算给定数组的结尾键名,第5行用于计算数组里中间元素的键名,并对小数的情况进行四舍五入。

第6行代码用于判断当开始与结尾键名不合法时,返回查找失败的提示信息;第8行用于判断中间元素的值大于查找值时,递归调用bSearch()函数,修改结尾键名。第10行用于判断中间元素的值小于查找值时,递归调用bSearch()函数,修改开始键名。第13行用于查找成功时,返回对应的键名。

4.PHP数组 - 图10

4.数组排序

1.冒泡排序

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

4.PHP数组 - 图11

  1. <?php
  2. function bubbleSort($arr)
  3. {
  4. //外层循环控制需要比较的轮数
  5. for ($i = 1,$len = count($arr);$i < $len; ++$i) {
  6. for ($j = 0; $j < $len - $i; ++$j) { //内层循环控制参与比较的元素
  7. if ($arr[$j] > $arr[$j + 1]) { //比较相邻的两个元素
  8. $temp = $arr[$j];
  9. $arr[$j] = $arr[$j + 1];
  10. $arr[$j + 1] = $temp;
  11. }
  12. }
  13. }
  14. return $arr;
  15. }
  16. $arr = [10,2,5,27,98,31];
  17. print_r(bubbleSort($arr)); //输出:Array ( [0] => 2 [1] => 5 [2] => 10 [3] => 27 [4] => 31 [5] => 98 )
  18. ?>

上述第5行代码用于循环冒泡排序的轮数,第6~12行代码用于循环比较数组中两个相邻的元素,如果当前元素大于后一个元素时,则通过第8~10行代码交换两个元素的值。编写完成后,调用函数bubbleSort(),将数组按照从小到大的顺序进行排序。

需要注意的是,冒泡排序的效率很低,在实际中使用较少。

2.简单选择排序

简单选择排序是一种非常直观的排序算法。它的实现原理是,从待排序的数组中选出最小或最大的一个元素与数组的第1个元素互换,接着再在剩余的数组元素中选择最小的一个与数组的第2个元素互换,依次类推,直到全部待排序的数组元素排序完成。如按照从小到大的顺序完成简单选择排序,具体实现如图所示。其中,图中利用箭头标注的两个元素就是在此次循环中互换的元素。

4.PHP数组 - 图12

  1. <?php
  2. function selectSort($arr)
  3. {
  4. for ($i = 0,$len = count($arr);$i < $len - 1;++$i){
  5. for ($j = $i + 1;$j < $len;++$j){
  6. if ($arr[$j] < $arr[$i]){
  7. $temp = $arr[$i];
  8. $arr[$i] = $arr[$j];
  9. $arr[$j] = $temp;
  10. }
  11. }
  12. }
  13. return $arr;
  14. }
  15. $arr = [9,1,2,10,4,12];
  16. print_r(selectSort($arr)); //输出:Array ( [0] => 1 [1] => 2 [2] => 4 [3] => 9 [4] => 10 [5] => 12 )
  17. ?>

在上述示例中,第4行用于循环遍历待排序数组,第5~11行代码用于循环遍历当前元素后所有的元素,并一一与其进行比较,只要小于当前元素就进行互换,直到选出最小的元素,依次类推,完成所有元素的排序。

值得一提的是,选择排序是不稳定的排序方法,在实际应用中使用也比较少。

3.快速排序

快速排序是对冒泡排序的一种优化。它的实现思路是,首先选择一个基准元素,通常选择待排序数组的第1个数组元素。通过一趟排序,将要排序的数组分成两个部分,其中一部分比基准元素小,另一部分比基准元素大,然后再利用同样的方法递归地排序划分出的两部分,直到将所有划分的数组排序完成.

4.PHP数组 - 图13

  1. <?php
  2. function quickSort($arr)
  3. {
  4. //获取待排序数组长度,当小于或等于1时直接返回数组(递归出口)
  5. $len = count($arr);
  6. if($len <= 1){
  7. return $arr;
  8. }
  9. //设置基准元素
  10. $pivot = $arr[0];
  11. $small = $big = [];
  12. //根据基准元素,将数组分成2个部分:小于和大于
  13. for ($i = 1;$i < $len;++$i){
  14. if ($arr[$i] < $pivot) { //小于基准元素
  15. $small[] = $arr[$i];
  16. }else { //大于等于基准元素
  17. $big[] = $arr[$i];
  18. }
  19. }
  20. //分别采取相同方案递归排序小于、大于部分的数组,然后进行合并
  21. return array_merge(quickSort($small),[$pivot],quickSort($big));
  22. }
  23. $arr = [31,98,5,27,2,78];
  24. print_r(quickSort($arr)); //输出:Array ( [0] => 2 [1] => 5 [2] => 27 [3] => 31 [4] => 78 [5] => 98 )
  25. ?>

在上述代码中,quickSort()函数传递的4.PHP数组 - 图14arr分为小于基准和大于等于基准元素两部分,第21行代码用于分别递归调用quickSort()处理小于和大于基准元素的排列,然后使用PHP提供的内置数组函数array_merge()完成排序后数组元素的合并。

4.插入排序

插入排序也是冒泡排序的优化,是一种直观的简单排序算法。它的实现原理是,通过构建有序数组元素的存储,对未排序数组的元素,在已排序的数组中从最后一个元素向第一个元素遍历,找到相应位置并插入。其中,待排序数组的第1个元素会被看作是一个有序的数组,从第2个至最后一个元素会被看作是一个无序数组。如按照从小到大的顺序完成插入排序,具体实现如图4-9所示。

4.PHP数组 - 图15

从图中可以看出,插入排序比较的次数与无序数组的长度相等,每次无序数组元素与有序数组中的所有元素进行比较,比较后找到对应位置插入,最后即可得到一个有序的数组。

  1. <?php
  2. function insertSort($arr)
  3. {
  4. for ($i = 1,$len = count($arr);$i < $len; ++$i){ //遍历无序数组
  5. for ($j = $i;$j > 0; --$j) { //遍历有序数组
  6. if ($arr[$j] < $arr[$j -1]) { //无序与有序进行比较
  7. $temp = $arr[$j];
  8. $arr[$j] = $arr[$j - 1];
  9. $arr[$j - 1] = $temp;
  10. }
  11. }
  12. }
  13. return $arr;
  14. }
  15. $arr = [98,7,65,54,12,6];
  16. print_r(insertSort($arr)); //输出:Array ( [0] => 6 [1] => 7 [2] => 12 [3] => 54 [4] => 65 [5] => 98 )
  17. ?>

在上述示例中,假设用户传递进来的数组4.PHP数组 - 图16arr中剩余的元素为无序数组。然后通过第4~12行代码进行循环。其中,第5~11行代码用于无序数组元素与有序数组中的所有元素进行比较,若无序元素4.PHP数组 - 图17j]小于有序数组中的元素,则进行插入。最后通过第13行代码将排序后的数组返回。

5.数组的常用函数

1.指针操作函数

函数名称 功能描述
current() 获取数组中当前指针指向元素的值
key() 获取数组中当前指针指向的元素的键
next() 将数组中的内部指针向前移一位
prev() 将数组中的内部指针倒回一位
each() 获取数组中当前的键值对并将数组指针向前移动一步
end() 将数组中的内部指针指向最后一个元素
reset() 将数组中的内部指针指向最后一个元素

1.通过指针函数访问数组

  1. <?php
  2. $arr = ['a','b','c','d','e'];
  3. echo key($arr).'--'.current($arr); //输出:0--a
  4. echo next($arr); //输出:b
  5. echo end($arr); //输出:e
  6. echo prev($arr); //输出:d
  7. echo reset($arr); //输出:a
  8. ?>

2.通过each()函数访问数组

each()函数可以获取数组中当前元素的键和值,并以数组形式返回,具体如下。

  1. <?php
  2. $arr = ['sub'=>'PHP'];
  3. echo '
  4. <pre>';
  5. print_r(each($arr));
  6. echo '
  7. <pre>';
  8. ?>

输出结果:

  1. The each() function is deprecated.
  2. Array
  3. (
  4. [1] => PHP
  5. [value] => PHP
  6. [0] => sub
  7. [key] => sub
  8. )

2.数组元素操作函数

在操作数组过程中,经常会遇到在数组的前面或后面添加或删除元素的情况。为此,PHP提供了几个入栈和出栈的函数.

函数名称 功能描述
array_pop() 将数组最后一个元素弹出(出栈)
array_push() 将一个或多个元素压入数组的末尾(入栈)
array_unshift() 在数组开头插入一个或多个元素
array_shift() 将数组开头的元素移出数组
array_unique() 移出数组中重复的值
array_slice() 从数组中截取部分数组
array_splice() 将数组中的一部分元素去掉并用其他值取代
  1. <?php
  2. $arr = ['a','b'];
  3. array_pop($arr); //输出:Array ( [0] => a )
  4. print_r($arr);
  5. array_push($arr,'c'); //输出:Array ( [0] => a [1] => c )
  6. print_r($arr);
  7. array_unshift($arr,'d','e'); //输出:Array ( [0] => d [1] => e [2] => a [3] => c )
  8. print_r($arr);
  9. array_shift($arr); //输出:Array ( [0] => e [1] => a [2] => c )
  10. print_r($arr);
  11. ?>

从上述代码可以看出,array_shift()和array_unshift()函数对于元素的数字键名会重新进行分配。

3.排序函数

PHP还提供了内置的数组排序函数,可以轻松对数组实现排序、逆向排序、按键名排序等操作。

函数名称 功能描述
sort() 对数组排序(从低到高)
rsort() 对数组排序(从高到低)
asort() 对数字进行排序并保持键值关系
ksort() 对数组按照键名排序
arsort() 对数组进行逆向排序并保持键值关系
krsort() 对数组按照键名逆向排序
shuffle() 将数组元素顺序打乱
array_multisort() 对多个数组或多维数组进行排序
  1. <?php
  2. $arr = ['a','c','b'];
  3. sort($arr);
  4. print_r($arr); //输出:Array ( [0] => a [1] => b [2] => c )
  5. rsort($arr);
  6. print_r($arr); //输出:Array ( [0] => c [1] => b [2] => a )
  7. asort($arr);
  8. print_r($arr); //输出:Array ( [2] => a [1] => b [0] => c )
  9. arsort($arr);
  10. print_r($arr); //输出:Array ( [0] => c [1] => b [2] => a )
  11. krsort($arr);
  12. print_r($arr); //输出:Array ( [2] => a [1] => b [0] => c )
  13. ?>

4.检索函数

函数名称 功能描述
in_array() 检查数组中是否存在某个值
array_search() 在数组中搜索给定的值,如果成功则返回相应的键名
array_key_exists() 检查给定的键名是否存在与数组中
  1. <?php
  2. $arr = ['a'=>1,'b'=>2,'c'=>3];
  3. var_dump(in_array(2,$arr)); //输出:bool(true)
  4. var_dump(array_search(2,$arr)); //输出:string(1) "b"
  5. var_dump(array_key_exists(2,$arr)); //输出:bool(false)
  6. ?>

5.其他数组函数

PHP还提供了很多其他常用的数组函数,具体可参考PHP手册。

函数名称 功能描述
count() 计算数组中的元素数目或对象中的属性个数
range() 建立一个包含指定范围元素的数组
  1. <?php
  2. $arr = ['a'=>1,'b'=>2,'c'=>3];
  3. print_r(count($arr)); //输出:3
  4. $arr2 = range(1,5);
  5. print_r($arr2); //输出:Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 )
  6. ?>