Go to comments

PHP 数组

什么是数组?

一个变量一般只能存一个值,而数组是一个变量里面可以存多个值。


首先PHP里面有八种数据类型,其中数组Array是非常重要的一种数据类型(一个项目中使用数组占30%)

第一: 把若干变量,按有序的形式,组织起来的一种形式,这些数据元素的集合称为数组

第二: 数组按下标个数分有两类,

         1). 一维数组,

         2). 二维数组等,二维以上的数组通常称"多维数组"

第三:数组是一个容器,使用的目的是可以批量操作


解释一

在别的语言里一般这样定义数组,把相关类型的若干变量,按有序的形式组织在一起,

而PHP中数组的确切概念应该是,把若干个变量组织在一起,不分相关的元素,也不分有没有序,所以PHP数组是特别灵活的数组,这也是PHP的一个特点。

使用数组的目的就是为了批量操作,通常把相关的数据放到一个组里面,我们只要对这个组操作,就对所有组中的成员操作了,这是使用数组最主要的目的。


在PHP中有按照下标不同分两种数组,索引数组 和 关联数组

索引(indexed):数组的索引值是整数,以0开始(但不一定是连续的)

关联(associative):数组以"字符串作为索引值",关联数组更像操作表。索引值为列名,用于访问列的数据。


解释二

在别的一些语言里面,数组都是有序的,数组里面必须是键 => 值映射,数组下标只有一种类型,就是索引数组(数组下标是0,1,2,3…),而PHP数组是多样的,声明也有多种方式


比如,下标可以是数字0对应的值,也可以是字符串对应的值

$arr = array('one', 10, 13, 4, true);


整数是下标的是"索引数组",字符串是下标是叫"关联数组"

$arr[0] = 'a'; // 索引数组

$arr['one'] = 'b'; // 关联数组


PS:

PHP中的数组实际上是一个有序的图,图是一种把values映射到keys的类型,

此类型在很多方面做了优化,因此可以把他当成真正的数组来使用,或列表(矢量),散列表(是图的一种实现),字典,集合,栈,队列以及更多可能性。因为可以用另一个PHP数组作为值,也可以很容易的模拟树。


解释三

别的语言数组的定义,比如C语言或java的数组,是相关类型的,有序的,多个元素的集合。

比如C语言 int a[10] = 这个声明体现了两个信息

第一个信息类型,数组里面只能存整数,浮点数、布尔型都存不了

第二个信息a[10]中括号里面10,里面必须存10个,多一个少一个都不行

别的一些语言里,数组有两个限制,一个是类型限制必须是相关类型,第二个是长度的限制。所以别一些语言要想实现类型不限、长度不限制,经常做一些容器


PS:

比如,C语言里面经常做列表,单线列表,双线列表……堆、栈

JAVA里面经常做集合、图、树、堆、栈……

所以在C语言里面,要想学数据结构,什么堆、栈、列表,有可能要花一周的时间

如果在JAVA里面学那些集合,也要将近一周的时间,才能学明白,然后用起来还不太灵活。


而PHP的数组,那些数据结构(数据结构容器)要学的东西,PHP数组全部搞定,

所以在PHP里面不用学堆、栈、图、列表、数……这些都不用学,就可以编程,所以PHP数组在项目中的应用占到30%,而别的一些语言里面,数组,还有那些容器,加在一起才应用到30%,

而且PHP数组非常好理解,使用还容易


PHP数组的特点:

1). 长度没有限制(数据别超过服务器限制的最大内存,不然会内容溢出)

2). 类型没有限制(篮子里装水果也行,装矿泉水也行)


数组特性(PHP数组的一些特征)

1、一个数组中存的是多个内容,数组中的内容叫作"元素"

2、每个元素都是由"键 和 值"两部分组成的(别的语言里可能叫哈希)

3、通过键(key)下标来使用值,下标分两种类型,

     1). 整数(索引数组)

     2). 字符串(关联数组)

4、使用[]中括号操作下标,也可以使用花括号{},建议使用[]中括号来指定下标

5、在使用下标时候,如果是关联数组,一定要使用引号(单引号,双引号都行),不要使用常量名称

6、数组的下标是自动增长的,默认是从0开始的,自动增长的都是出现过的最大值加 1

7、关联数组的字符串下标,不会影响索引下标的排列规则

8、使用array()函数声明数组,默认是索引的下标,是从0开始的

9、array()函数声明数组,使用"=>"符号指定下标(PHP5.4以后,可以像其它语言一样声明数组了)

10、删除数组中的一个元素,使用的是unset(),数组下标不会重新索引,需要使用array_value()函数重新索引


PHP中的数组声明有多种方式,PHP数组的应用是非常灵活的,创建数组也是非常灵活的,

当然除了我们自己创建的数组,后期程序的应用也会自动生成一些数组,比如链接msysql数据库,返回数据表里面存的内容的数组。

一、数组的定义(声明)

1、直接赋值声明数组

2、使用array()语言结构声明数组

3、PHP5.4版本新的中括号声明方式 []

4、多维数组的声明


特征

1、一个数组中存的是多个内容,数组中的内容叫作"元素"

2、每个元素都是由"键 和 值"两部分组成的(别的语言里可能叫哈希)


键(key)和值(value)是一种映射关系,键(key)也叫下标。变量$arr是数组类型,里面有两个元素,第二个元素的键(下标)是['two'],值是"222"

$arr = array("one"=>"111", "two"=>"222");

$arr['two']; // 222


PHP声明数组从语法上来说,在早期PHP2.0版本里面支持两种方式,

1). 一种是直接赋值声明

2). 一种是使用array()函数声明

3). 还有一种是PHP5.4以后新增的 [] 声明方法


特性

3、通过键(key)下标来使用值。下标分两种类型,1). 整数(索引数组),2). 字符串(关联数组)

1、直接赋值声明数组

索引数组

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

print_r($arr); // Array ( [0] => 1 [1] => 2 [2] => 3 )


关联数组

$arr['one'] = 1;
$arr['two'] = 2;
$arr['three'] = 3;

print_r($arr); // Array ( [one] => 1 [two] => 2 [three] => 3 )


总结:

直接赋值声明数组,就是直接使用中括号,在一个变量里面开辟出多个下标,下标可以无限的加下去没有长度的限制。

索引数组 和 关联数组的区别很明显,就是下标是整数还是字符串。

二、数组的下标

特征

4、使用[]中括号操作下标,也可以使用花括号{},建议使用[]中括号来指定下标


中括号来操作

$arr['one'] = 1;
$arr['two'] = 2;
$arr['three'] = 3;

echo $arr['one'],'<br/>'; // 1

echo $arr{'three'}; // 3


用花括号下标访问数组,数组声明也能用花括号

$arr{'one'} = 1;
$arr['two'] = 2;
$arr['three'] = 3;

echo $arr{'one'}; // 1

实际使用中不建议用花括号{},用的人非常少,因为其它语言都是用中括号


注意一点:

字符串中嵌套变量时,用花括号断开,意思是当做特殊符号把变量隔出来,

但是数组的中括号不算特殊符号(很多人以为[]是特殊符号,其实不是特殊符号),中括号放到数组里面,是"数组变量名"的一部分,

所以字符串在解析的时候,遇到中括号[]不算是特殊字符,不会把变量断开


下面数字 123 被嵌入到字符串中

$arr['one'] = '123';

echo "I am not$arr[one]available"; // I am not123available

字符串中数组下标用花括号,在解析字符串的时候不算是特殊符号

$arr['one'] = '123';

echo "I am not$arr{one}available"; // I am notArray{one}available

输出的字符串,不解析变量,而且还报注意:Notice: Array to string conversion in……

建议使用中括号[],不建议使用花括号{}


特征

5、在使用下标时候,如果是关联数组,一定要使用引号(单引号,双引号都行),不要使用常量名称


使用关联数组的时候,下标是字符串形式,字符串必须用双引号或单引号引起了,推荐用单引号,因为效率比双引号高

$arr[four] = 4;

echo $arr[four]; // 4


/**
 * 1.如果不加单引号或双引号,里面的four按照常量解析,
 * 2.没有声明常量的情况下,常量名four会转成字符串
 * 3.这样虽然能打印出值4,但是系统会报注意/警号信息,虽然不是报错信息,但是效率会很低
 * 因为系统检查常量不存在的情况下,会转成字符串,这个效率会比直接使用字符串慢
 *
 * PHP7版本中系统报错Warning信息
 * Warning: Use of undefined constant four - assumed 'four' (this will throw an Error in a future version of PHP) in ……
 */

这个细节也是应该注意的,用关联数组的时候,下标是字符串,就要用引号印起来,这个细节点很重要

数组的"索引下标"和"关联下标",是可以同时存在的,但是也不建议这样用

但是通过PHP系统函数返回的数组,一般都返回这两种在一起的形式,凭我们的喜好选择索引下标或关联下标

$arr[0] = 1;
$arr[1] = 2;
$arr[2] = 3;
$arr{'one'} = 1;
$arr['two'] = 2;
$arr['three'] = 3;

print_r($arr); // Array ( [0] => 1 [1] => 2 [2] => 3 [one] => 1 [two] => 2 [three] => 3 )

PHP索引和关联数组需要注意的细节

3、key的强制转换

数组的下标就是"整形"和"字符串"两种,但是变量有八中类型,PHP又是弱类型语言,弱类型语言意味着其它类型作为下标也没问题。

是没有问题,但是PHP数组下标只支持整数和字符串这两种,其它的会被自动强制转换

细节1:包含有,合法整型的字符串,会被转换为整型

例如:字符串的下标"2"会被存为整形2

$arr[0] = 1;
$arr[1] = 2;
$arr["2"] = 3; // 字符串"2"做下标,打印结果下标还是2

print_r($arr); // Array ( [0] => 1 [1] => 2 [2] => 3 )

但是字符串"02"不会强制转换,因为其不是一个合法的十进制数值,"02"是八进制的数

$arr[0] = 1;
$arr[1] = 2;
$arr["02"] = 3; // 字符串"02"不会强制转换,因为其不是一个合法的十进制数值,"02"是八进制的数

print_r($arr); // Array ( [0] => 1 [1] => 2 [02] => 3 )

这个细节面试时可能会提到

细节2:浮点数也会被转换为整数,但是其小数部分会被舍去。例如:键名2.7,实际会被储存为2

PHP好些地方强制类型转换都是割舍的,key: 2.7 实际会被储存为2

$arr[0] = 1;
$arr[1] = 2;
$arr[2.7] = 3;  // 键名2.7实际会被储存为2

print_r($arr); // Array ( [0] => 1 [1] => 2 [2] => 3 )

细节3:布尔值做下标也会被转换成整形。既,键名true实际被存储为1,而键名false会被存储为0。

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

$arr[true] = 'true覆盖';  // true会转换成1,会把上面的$arr[1]=2给覆盖了
$arr[false] = 'false覆盖'; // false会被转换成0,把上面的$arr[0]=>1给覆盖了

print_r($arr); // Array ( [0] => false覆盖 [1] => true覆盖 [2] => 3 )

细节4:Null会被转换为空字符串。既,键名Null实际会被存储为空字符串""

总结:

索引可以用中括号,或花括号,建议用中括号

索引数组和关联数组是可以在一起用的

常量名称,别作为数组下标,可以做但是会有效率的影响

各种变量类型都可以做数组下标,但是会强制转换成,索引数组和关联数组

继续讨论,继续讨论数组声明的细节问题

细节6:如果在数组定义多个单元都使用了同一个键名,则只有使用了最后一个,之前的都被覆盖了

这种情况就像是,前面出现了一变量$a,后面又给变量$a重新赋值,是一个重新覆盖的问题

虽然这个问题很小但很重要,操作的是同一个元素,所以第二个元素给第一个元素重新赋值了

$arr[0] = 10;

$arr[0] = 30; // 后面又出现一个下标为10的单元

print_r($arr); // Array ( [0] => 30 )

如果声明数组的时候,下标可以不连续吗?

如果是其它一些语言这是不行的,其它语言只有索引数组,而且下标必须连续的

PHP里的数组下标可以不用整数,可以用字符串,另外是整数下标还可以不连续

$arr[0] = 10;

$arr[100] = 30;

print_r($arr); // Array ( [0] => 10 [100] => 30 )

特征6:数组的下标是自动增长的,默认是从0开始的,自动增长的都是出现过的最大值加一

如果不指定下标,下标会逐一的自动增加

$arr[] = 'one';
$arr[] = 'two';
$arr[] = 'three';
$arr[] = 'four';
$arr[] = 'five';
$arr[] = 'six';
$arr[] = 'seven';
$arr[] = 'eight';
$arr[] = 'nine';
$arr[] = 'ten';

print_r($arr); // Array ( [0] => one [1] => two [2] => three [3] => four [4] => five [5] => six [6] => seven [7] => eight [8] => nine [9] => ten )

通常写一个循环向数组里添加很多东西

$arr = array(); // 声明一个数组(不声明也行)

for($i = 0; $i < 100; $i++){

	$arr[] = $i * $i;

}

print_r($arr); // Array ( [0] => 0 [1] => 1 [2] => 4 [3] => 9……)

// 建一个空容器,再循环往容器里装很多个值,就用这个办法

如果下面这样,突然中间有一个下标8出现,下标会在最大值8上加1

$arr[] = 1;
$arr[] = 2;
$arr[] = 3;
$arr[8] = 4; // 突然有一个下标8出现
$arr[] = 5;
$arr[] = 6;
$arr[] = 7;
$arr[] = 8;
$arr[] = 9;

print_r($arr); // Array ( [0] => 1 [1] => 2 [2] => 3 [8] => 4 [9] => 5 [10] => 6 [11] => 7 [12] => 8 [13] => 9 )



/***
下标是从0开始的(国外的楼一层是标的是0层),下标会在最大值8上加1,而是从9,10,11……继续往后排

Array
(
    [0] => 1
    [1] => 2
    [2] => 3
    [8] => 4
    [9] => 5
    [10] => 6
    [11] => 7
    [12] => 8
    [13] => 9
)
***/

下标默认从0开始,后面出现前面一样的下标,就把前面的值覆盖,如果不出现一样的下标就自动用最大下标值加一

$arr[] = 1;
$arr[] = 2;
$arr[] = 3;
$arr[8] = 4; // 1. 指定了下标8
$arr[] = 5;  // 2. 上面指定了下标8 这里的下标是9
$arr[9] = 6; // 3. 这里下标还是9,会把上面($arr[] = 5;)覆盖掉
$arr[] = 7;
$arr[4] = 8; // 这块在出现一个4的下标,4后面的下标是11,不会补齐之前空缺的键
$arr[] = 9;

print_r($arr); // Array ( [0] => 1 [1] => 2 [2] => 3 [8] => 4 [9] => 6 [10] => 7 [4] => 8 [11] => 9 )

/***
Array
(
    [0] => 1
    [1] => 2
    [2] => 3
    [8] => 4
    [9] => 6
    [10] => 7
    [4] => 8
    [11] => 9
)
****/

特征7:关联数组的字符串下标,不会影响索引下标的排列规则

$arr[] = 1;
$arr[] = 2;
$arr[] = 3;
$arr[8] = 4;
$arr[] = 5;
$arr[9] = 6;
$arr[] = 7;
$arr[4] = 8;
$arr[] = 9;
$arr['ten'] = 10; // 这里出现一个字符串下标
$arr[] = 11;      // 问这个下标是多少?是12

print_r($arr); // Array ( [0] => 1 [1] => 2 [2] => 3 [8] => 4 [9] => 6 [10] => 7 [4] => 8 [11] => 9 [ten] => 10 [12] => 11 )


/***
Array
(
    [0] => 1
    [1] => 2
    [2] => 3
    [8] => 4
    [9] => 6
    [10] => 7
    [4] => 8
    [11] => 9
    [ten] => 10
    [12] => 11
)
***/

索引下标是整形,除了非法字符(八进制、十六进制)不能做下标,整形有正负数,如果用负数做下标会怎么样呢?

1). 负数是可以做下标的,只是平时习惯了用正数做下标从0开始增长,但是PHP是支持负数的

2). 但是自动增长的都是出现过的最大值加一,负数不是最大值

-100是最小值,后面自动增长的索引,不会受到-100影响

$arr[] = 1;
$arr[] = 2;
$arr[] = 3;
$arr[] = 4;
$arr[] = 5;
$arr[-100] = -6; // 这里出现负-100,后面的下标是怎么自增长
$arr[] = 7;
$arr[] = 8;
$arr[] = 9;

print_r($arr); // Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 [-100] => -6 [5] => 7 [6] => 8 [7] => 9 )


/***
Array
(
    [0] => 1
    [1] => 2
    [2] => 3
    [3] => 4
    [4] => 5
    [-100] => -6
    [5] => 7
    [6] => 8
    [7] => 9
)
***/

索引下标自动增长的一些问题,面试题出的比较多。

4、array()声明数组

PHP声明数组有多种方法,array()函数声明数组也是非常常用的

说array()是一个函数,其实并非是一个真正的函数,跟include、echo一样相当一个系统指令

比如用function_exists()判断array函数是否存在,判断结果是"不存在",但是手册上确实有array()函数,像这样的函数还有。

if(function_exists("array")){

	echo '存在';

}else{

	echo '不存在'; // 不存在

}

PS:

key可以是integer或者string,value可以是任意类型

应该始终在用字符串表示的数组索引上加引号,例如$foo['far']而不是$foo[bar]

特征8:使用array()函数声明数组,默认是索引的下标,而且是从0开始的

默认是索引的下标,都是是从0开始的

$arr = array('one', 'two', 'three', 'four');

print_r($arr); // Array ( [0] => one [1] => two [2] => three [3] => four )

特征9:array()函数声明数组,使用"=>"符号指定下标(PHP5.4以后,可以像其它语言一样声明数组了)

array()声明数组

1). 下标还是有索引下标 和 字符串下标两种

2). 自动增长的下标,默认从0开始

3). 如果出现同一个键名,后面出现的覆盖前面的键、值

4). 自动增新元素的键,在最大键值上加一

5). 关联数组的下标,不会影响到索引数组下标的自动增长

跟之前"直接赋值"声明数组是一样的

$arr = array('one', 'second'=>'two', 9=>'three', 'four');

print_r($arr); // Array ( [0] => one [1] => two [2] => three [3] => four )

中括号声明数组

PHP5.4以后,可以像JS语言一样声明数组了

<script>

	var arr = [1,2,3,4,5,6];

	alert(arr[1]); // 2
	
</script>

PHP5.4以后支持了这种,直接使用中括号的声明数组

$arr = ['one', 'two', 'three', 'four'];

print_r($arr); // Array ( [0] => one [1] => two [2] => three [3] => four )

中括号声明数组的方式和array()是一样的,只是形式不一样其它都一样

$arr = ['one', 'second'=>'two', 9=>'three', 'four'];

print_r($arr); // Array ( [0] => one [second] => two [9] => three [10] => four )

"中括号"声明数组,还有一个新的功能:

如果函数里面返回一个数组,如果PHP5.4之前,函数的执行先赋给一个临时变量,然后再临时变量显示出数组内容

function demo(){
	return array('one', 'two', 'three', 'forth'); 
}

$arr = demo(); // 返回的数组赋给一个临时变量$arr

echo $arr[0]; // one

新版本里,直接调用函数执行 + 数组下标

function demo(){
	return array('one', 'two', 'three', 'forth'); 
}

echo demo()[1]; // two

5、删除数组中的元素

特征10:删除数组中的一个元素,使用的是unset(),数组下标不会重新索引,需要使用array_value()函数重新索引

删除变量时用的是unset()函数

让变量不存在,有两种办法,一种是unset()函数将内存中的变量释放掉了

$a = 123;

unset($a); // 执行到这,将内存中的变量释放掉了

if(isset($a)){ // isset判断变量是否存在

	echo '存在';

}else{

	echo '不存在'; // 不存在

}

或者将变量$a赋值为空null,跟unset()函数的作用是一样的

$a = 123;

$a = null;

if(isset($a)){

	echo '存在';

}else{

	echo '不存在'; // 不存在

}

使用unset()删除数组中的元素

$arr = ['one', 'two', 'three', 'four', 'five', 'six'];

unset($arr[2]);

if(isset($arr[2])){ 

	echo '存在';

}else{

	echo '不存在'; // 不存在

}

或者$arr[2]赋值为null,isset判断也是不存在的

$arr = ['one', 'two', 'three', 'four', 'five', 'six'];

$arr[2] = null;

if(isset($arr[2])){

	echo '存在';

}else{

	echo '不存在'; // 不存在

}

如果用 $arr[2] = null 删除一个数组元素后,用print_r($arr)打印数组,arr[2]单元还在,只是值没有了

$arr = ['one', 'two', 'three', 'four', 'five', 'six'];

$arr[2] = null;

print_r($arr); // Array ( [0] => one [1] => two [2] => [3] => four [4] => five [5] => six )


/***
arr[2]赋值为null的结果

Array
(
    [0] => one
    [1] => two
    [2] => 
    [3] => four
    [4] => five
    [5] => six
)
***/

用unset(arr[2])删除,数组没有了这个$arr[2]单元

$arr = ['one', 'two', 'three', 'four', 'five', 'six'];

unset($arr[2]);

print_r($arr); // Array ( [0] => one [1] => two [3] => four [4] => five [5] => six )


/***
unset(arr[2])删除结果

Array
(
    [0] => one
    [1] => two
    [3] => four
    [4] => five
    [5] => six
)
***/

所以在数组里面用unset($arr[2])删除,和赋值为空$arr[0] = null还不太一样。

$arr[0] = null;  值为空

unset($arr[2]);  整个变量没有了,虽然整个变量没有了,但是下标的顺序并没有重新索引,

实例,猴子选大王

比如有15只猴子,随便指一个猴子(比如,3),从3开始数数,每次数到3的倍数时,就把那个就踢出去……,最后剩下的就是大王

/**
 * xdw($m, $n) 
 * $m   猴子的数量
 * $n   随便指的一个数
 *
 */

function xdw($m, $n){
	$arr = array(); // 声明一个空数组
	
	$a = 'a';
	
	for($i=0; $i<$m; $i++){
		$arr[] = $a++; // 字符串的加加,是abcd……的累积
	}
	
	// print_r($arr); // 打印出猴子
	
	// 下面开始选大王
	
	$i = 0; // 从0开始,下面while里面每循环一次$i++(不能从1开始,不然结果永远数到第0个)
	
	while(count($arr) > 1){ // 数组的个数大于1,就一直循环
		
		if($i%$n == 0){ // 与$n取余的就删掉
			unset($arr[$i]); // 1 把猴子踢出去,删除一个
		}else{
			$arr[] = $arr[$i]; // 2 踢出去的猴子(3)就不要了,数过的没踢出去的猴子(1,2),放到$arr数组后面
			unset($arr[$i]);   // 3 数过的猴子,原地删除,这样数组的长度每隔3个单元就少一个单元
		}
		
		$i++;            
	}
	
	return $arr; // 返回的数组里面,剩下的一个就是大王
}

print_r(xdw(31, 3)); // Array ( [88] => ad )

6、多维数组

PHP中的数组,除了关联数组 和 索引数组,根据下标类型区分之外,还有维度上的区别。有一维数组、二维数组,三维数组,以及多维数组,二维以上都称为多维数组

我们知道,数组里面可以装任何类型,整形、字符串型、浮点型、布尔型,数组里面也可以再装一个数组

其实在PHP里面没有二维、多维数组这样的说法,都叫做数组中的数组

只不过经历过C语言,JAVA语言的数组使用,习惯上管PHP数组的数组叫二维数组,其实叫数组的数组更合适。说白了就是在数组里面再存放数组。


二维数组(数组中的数组)

比如,在一个数组里面,声明三个人的联系信息

/**
 * 第一个人$personOne
 * 第二个人$personTwo
 * 第三个人$personThree
 * 用关联数组来声明这种和生活中业务相关的,通过记下标名称比较方便
 *
 */

$personOne = array('name'=>'Lin', 'age'=>'32', 'sex'=>'男', 'email'=>'lin@ruyic.com');

$personTwo = array('name'=>'Zhu', 'age'=>'21', 'sex'=>'女', 'email'=>'Zhu@ruyic.com');

$personThree = array('name'=>'Yu', 'age'=>'34', 'sex'=>'男', 'email'=>'Yu@ruyic.com');

/**
 * 一个人用,一个一维数组, 
 * 把三个人的数组,放到一组$group里
 * 
 */

$group = array($onePerson, $twoPerson, $threePerson);

print_r($group);

echo $group[1]['name']; // Zhu

平时是这么做的,数组是可以嵌套的

$group = array(
		array('name'=>'Lin', 'age'=>'32', 'sex'=>'男', 'email'=>'lin@ruyic.com'),
		array('name'=>'Zhu', 'age'=>'21', 'sex'=>'女', 'email'=>'Zhu@ruyic.com'),
		array('name'=>'Yu', 'age'=>'34', 'sex'=>'男', 'email'=>'Yu@ruyic.com')
);

echo $group[1]['name'],'<br/>'; // Zhu

$arr = $group[1];

echo $arr['email']; // Zhu@ruyic.com

第三个数组用字符串下标

$group = array(
		array('name'=>'Lin', 'age'=>'32', 'sex'=>'男', 'email'=>'lin@ruyic.com'),
		array('name'=>'Zhu', 'age'=>'21', 'sex'=>'女', 'email'=>'Zhu@ruyic.com'),
		'three'=>array('name'=>'Yu', 'age'=>'34', 'sex'=>'男', 'email'=>'Yu@ruyic.com')
);

echo $group['three']['email'],'<br/>'; // Yu@ruyic.com

总结:

二维数组的声明方式,重点就是二维数组就是"数组的数组",跟一维数组访问上、结构上都一样,只不过数组里面多了一层而已。


三维数组:

三维数组的声明(在PHP5.4版本以后,可以像js里面用中括号的方式声明数组)

/***
$groupOne = [
			['name'=>'Lin', 'age'=>'32', 'sex'=>'男', 'email'=>'lin@ruyic.com'],
            ['name'=>'Zhu', 'age'=>'21', 'sex'=>'女', 'email'=>'Zhu@ruyic.com'],
			['name'=>'Yu', 'age'=>'34', 'sex'=>'男', 'email'=>'Yu@ruyic.com']
];

$groupTwo = [
			['name'=>'Lin', 'age'=>'32', 'sex'=>'男', 'email'=>'lin@ruyic.com'],
            ['name'=>'Zhu', 'age'=>'21', 'sex'=>'女', 'email'=>'Zhu@ruyic.com'],
			['name'=>'Yu', 'age'=>'34', 'sex'=>'男', 'email'=>'Yu@ruyic.com']
];
		
$groupTree = [
			['name'=>'Lin', 'age'=>'32', 'sex'=>'男', 'email'=>'lin@ruyic.com'],
            ['name'=>'Zhu', 'age'=>'21', 'sex'=>'女', 'email'=>'Zhu@ruyic.com'],
			['name'=>'Yu', 'age'=>'34', 'sex'=>'男', 'email'=>'Yu@ruyic.com']
];
***/


/**
 * 把三个数组组成一个班级,把三个数组组成一个班级,
 * 可以有关联数组,也可以有索引数组
 *
 */


$class = [
		[
			['name'=>'Lin', 'age'=>'32', 'sex'=>'男', 'email'=>'lin@ruyic.com'],
			['name'=>'Zhu', 'age'=>'21', 'sex'=>'女', 'email'=>'Zhu@ruyic.com'],
			['name'=>'Yu', 'age'=>'34', 'sex'=>'男', 'email'=>'Yu@ruyic.com']
		],
		'two' =>[
			['name'=>'Lin', 'age'=>'32', 'sex'=>'男', 'email'=>'lin@ruyic.com'],
			['name'=>'Zhu', 'age'=>'41', 'sex'=>'女', 'email'=>'Zhu@ruyic.com'],
			['name'=>'Yu', 'age'=>'34', 'sex'=>'男', 'email'=>'Yu@ruyic.com']
		],
		[
			['name'=>'Lin', 'age'=>'32', 'sex'=>'男', 'email'=>'lin@ruyic.com'],
			['name'=>'Zhu', 'age'=>'39', 'sex'=>'女', 'email'=>'Zhu@ruyic.com'],
			['name'=>'Yu', 'age'=>'34', 'sex'=>'男', 'email'=>'Yu@ruyic.com']
		]
];


echo '<pre>';
print_r($class);
echo '<pre/>';

echo $class['0'][1]['age'],'<br/>'; // 21

echo $class['two'][1]['age'],'<br/>'; // 41

echo $class[1][1]['age']; // 39

使用数组尽量控制在三维以内

多维数组还可以使用"直接赋值"的方式声明

$group[0]['name'] = 'Lin';
$group[0]['age'] = 20;
$group[1]['name'] = 'Zhu';
$group[1]['age'] = 32;

echo '<pre>';
print_r($group);
echo '</pre>';

/***
Array
(
    [0] => Array
        (
            [name] => Lin
            [age] => 20
        )

    [1] => Array
        (
            [name] => Zhu
            [age] => 32
        )

)
***/

通常这种"直接赋值声明法"是操作某一个或者是添加某一个的处理会方便些。


另外PHP的二维数组,三维数组有一个特点,不用像C语言的数组那样,必须是行列要对齐。

什么是行列对其?

要求数组是几行几列,就必须是几行几列,这才是真正的二维。而PHP数组,里面的数组可以是混合式的。

什么是混合式的?

一个数组里面可以装数组成员,和非数组成员的混合也是可以的。

比如,每个组里面除了组成员,还有组共有的信息,比如这个组所在的位置,这个组再班级的成绩,这些不属于某个人,而是属于组信息。

所以我们可以在数组里面存,数组和非数组的混合体。

总结

1). 二维数组中,并不一定二维中必须是数组,

2). 二维数组中,二维数组的长度,不一定非要相等


如果外层数组的下标都是[0],里层的二维数组不指定下标,那么里面的二维数组下标从0开始自动增长

$group[0][] = 'Lin';
$group[0][] = 20;
$group[0][] = 'Zhu';
$group[0][] = 32;

print_r($group); // Array ( [0] => Array ( [0] => Lin [1] => 20 [2] => Zhu [3] => 32 ) )


/***
Array
(
    [0] => Array
        (
            [0] => Lin
            [1] => 20
            [2] => Zhu
            [3] => 32
        )

)
***/

如果里层数组不指定下标,外层数组也不指定下标,外层数组自动从0增长,这种情况不多,了解一下就行了

$group[][] = 'Lin';
$group[][] = 20;
$group[][] = 'Zhu';
$group[][] = 32;

print_r($group); // Array ( [0] => Array ( [0] => Lin ) [1] => Array ( [0] => 20 ) [2] => Array ( [0] => Zhu ) [3] => Array ( [0] => 32 ) )

/***
Array
(
    [0] => Array
        (
            [0] => Lin
        )

    [1] => Array
        (
            [0] => 20
        )

    [2] => Array
        (
            [0] => Zhu
        )

    [3] => Array
        (
            [0] => 32
        )

)
***/

如果外层不指定下标,里层数组下标的默认值都是[1],里面的数组下标都是[1],外层数组自动从0增长

$group[][1] = 'Lin';
$group[][1] = 20;
$group[][1] = 'Zhu';
$group[][1] = 32;

print_r($group); // Array ( [0] => Array ( [1] => Lin ) [1] => Array ( [1] => 20 ) [2] => Array ( [1] => Zhu ) [3] => Array ( [1] => 32 ) )

/***
Array
(
    [0] => Array
        (
            [1] => Lin
        )

    [1] => Array
        (
            [1] => 20
        )

    [2] => Array
        (
            [1] => Zhu
        )

    [3] => Array
        (
            [1] => 32
        )

)
***/

总结规律

多维数组是外层(第一层)的下标先自动增长,

如果外面第一层数组下标给值,里面第二层的下标自动增长


外面的第一个数组下标是[9],自动增长的规律是一样的,下标从[10]开始

$group[9][] = 'Lin';
$group[][] = 20;
$group[][] = 'Zhu';
$group[][] = 32;

// print_r($group); // Array ( [9] => Array ( [0] => Lin ) [10] => Array ( [0] => 20 ) [11] => Array ( [0] => Zhu ) [12] => Array ( [0] => 32 ) )

/***
Array
(
    [9] => Array
        (
            [0] => Lin
        )

    [10] => Array
        (
            [0] => 20
        )

    [11] => Array
        (
            [0] => Zhu
        )

    [12] => Array
        (
            [0] => 32
        )

)
***/

直接赋值声明二维数组用的比较少,arrar()声明数组的方式用的非常的多。

课程PPT里面的二维数组,该用关联的用关联下标去访问,该用索引的用索引下标去访问

$contact = array(
	array(1, '高某', 'A公司', '北京市', '(010)98765432', 'gm@linux.com'),
	array(2, '洛某', 'B公司', '上海市', '(021)12345678', 'lm@apache.com'),
	array(3, '峰某', 'C公司', '天津市', '(022)24680246', 'fm@mysql.com'),
	array(4, '书某', 'D公司', '重庆市', '(023)13579135', 'sm@php.com')
);

echo '第一个人联系的公司:',$contact[0][2],'<br/>'; // 第一个人联系的公司:A公司

$contact = array(
	'北京联系人'=>array(1, '高某', 'A公司', '北京市', '(010)98765432', 'gm@linux.com'),
	'上海联系人'=>array(2, '洛某', 'B公司', '上海市', '(021)12345678', 'lm@apache.com'),
	'天津联系人'=>array(3, '峰某', 'C公司', '天津市', '(022)24680246', 'fm@mysql.com'),
	'重庆联系人'=>array(4, '书某', 'D公司', '重庆市', '(023)13579135', 'sm@php.com')
);

echo '上海联系人的EMAIL:',$contact['上海联系人'][5]; // 上海联系人的EMAIL:lm@apache.com

PPT里的三维数组

$wage = array(
	'市场部'=>array(
		array(1, '高某', '市场部经理', 5000.00),
		array(2, '洛某', '职员', 3000.00),
		array(3, '峰某', '职员', 2400.00)
	),
	'产品部'=>array(
		array(1, '李某', '产品部经理', 6000.00),
		array(2, '周某', '职员', 4000.00),
		array(3, '吴某', '职员', 3200.00)
	),
	'财务部'=>array(
		array(1, '郑某', '财务部经理', 4500.00),
		array(2, '王某', '职员', 2000.00),
		array(3, '冯某', '职员', 1500.00)
	)
);

print_r($wage['市场部']);

print_r($wage['市场部'][1]);

print_r($wage['市场部'][1][3]);

6、遍历数组

使用数组最主要的目的就是批量操作,批量操作最核心的是遍历数组,PHP里面对数组的遍历比其它的语言要多一些,因为PHP语言数组的结构比别的语言灵活一些。

数组的便利方式:

最主要的是for循环、PHP里面专门遍历数组的是foreach,还可以使用系统函数结合while循环去遍历数组

for语句遍历数组

高洛峰老师课程里说:for循环遍历数组效率很高,因为就是数组的访问方式,只不过是循环取值。就是一个循环的效率,所以效率很高,功能越全的效率越低。

下面使用array()语句将联系人列表中第一条记录,声明成一维数组,然后以表格的形式输出一维数组中的每一个单元

$contact = array(1, '高某', 'A公司', '北京市', '(010)12345678', 'gao@broPHP.com');

echo '<table border="1" width="600" align="center">
	<caption><h1>联系人列表</h1></caption>
	<tr bgcolor="#ddd">
		<th>编码</th>
		<th>姓名</th>
		<th>公司</th>
		<th>地址</th>
		<th>电话</th>
		<th>EMAIL</th>
	</tr>
	<tr>';

$nums = count($contact); // count()获取数组的长度

// 使用for循环,输出一维数组中的元素 for($i=0; $i<count($contact); $i++){ 优化一下,用计算好的数组长度$nums
for($i = 0; $i < $nums; $i++){
	echo "<td>{$contact[$i]}</td>";
}

echo '</tr></table>';

如果数组的下标不是连续的,其中一个数组下标变成12,这个下标12元素后面的就遍历不出来了

count()获取数组的实际元素的个数

下标[12]超过了数组的实际长度,后面的就循环不到了

$arr = array('one', 'two', 'three', 'four', 'five', 12=>'six', 'seven', 'eight', 'nine', 'ten');

$nums = count($arr);

for($i = 0; $nums > $i; $i++){
	echo $arr[$i],'<br>';
}

/***
one
two
three
four
five
Notice: Undefined offset: 5 in……
Notice: Undefined offset: 6 in……
Notice: Undefined offset: 7 in……
Notice: Undefined offset: 8 in……
Notice: Undefined offset: 9 in……
***/

别的语言里面数组下标是连续的,PHP数组可以不是连续的,所以for循环便利,优点是效率高

for循环一定要保证,数组下标是连续的索引数组

for循环遍历能遍历数组,但不是主力方式。f

or循环是模拟其它语言遍历数组,但不是PHP主要遍历数组的方式

for循环不足的地方

1). 数组下标不一定是连续的

2). 关联数组for循环不能遍历出值

索引数组和关联数组混合在一起,可以用foreach来遍历数组

foreach是专门遍历数组的语句

遍历二维数组

$group = [
			['name'=>'Lin', 'age'=>'32', 'sex'=>'男', 'email'=>'lin@ruyic.com'],
			['name'=>'Zhu', 'age'=>'21', 'sex'=>'女', 'email'=>'Zhu@ruyic.com'],
			['name'=>'Yu', 'age'=>'34', 'sex'=>'男', 'email'=>'Yu@ruyic.com'],
			['name'=>'Li', 'age'=>'32', 'sex'=>'男', 'email'=>'lin@ruyic.com'],
			['name'=>'Zh', 'age'=>'41', 'sex'=>'女', 'email'=>'Zh@ruyic.com'],
			['name'=>'Y', 'age'=>'34', 'sex'=>'男', 'email'=>'Y@ruyic.com']
		 ];

// print_r($group);

echo '<table border="1" width="800" align="center">';
echo '<caption><h1>数组转为表格</h1></caption>';

foreach($group as $row){
	echo '<tr>';
	
	print_r($row); // 打印的一行,还是数组,这里要再foreach循环一次
	
	echo '</tr>';
}

echo '</table>';

再用foreach循环

$group = [
			['name'=>'Lin', 'age'=>'32', 'sex'=>'男', 'email'=>'lin@ruyic.com'],
			['name'=>'Zhu', 'age'=>'21', 'sex'=>'女', 'email'=>'Zhu@ruyic.com'],
			['name'=>'Yu', 'age'=>'34', 'sex'=>'男', 'email'=>'Yu@ruyic.com'],
			['name'=>'Li', 'age'=>'32', 'sex'=>'男', 'email'=>'lin@ruyic.com'],
			['name'=>'Zh', 'age'=>'41', 'sex'=>'女', 'email'=>'Zh@ruyic.com'],
			['name'=>'Y', 'age'=>'34', 'sex'=>'男', 'email'=>'Y@ruyic.com']
		 ];

// print_r($group);

echo '<table border="1" width="800" align="center">';
echo '<caption><h1>数组转为表格</h1></caption>';

foreach($group as $row){
	echo '<tr>';

	foreach($row as $col){
		echo "<td> $col </td>"; // 循环一次输出一列
	}

	echo '</tr>';
}

echo '</table>';

联合使用list()、each()和while循环数组

list()和each()是函数,while是循环,这几个是不搭边的,但效率上和foreach查不多


list()函数

这个函数和其它函数用法不同,作用是将数组中的元素转为变量使用。

相当于将数组元素对应的转给成了对应的变量,而且还是顺序转换的

list($a, $b, $c) = array('one', 'two', 'three');

echo $a,'<br/>'; // one
echo $b,'<br/>'; // two
echo $c,'<br/>'; // three

只能转索引数组为变量,索引数组下标是连续

list($a, $b, $c) = array('one', 8=>'two', 'three');

echo $a,'<br/>'; // one
echo $b,'<br/>'; // 没有输出
echo $c,'<br/>'; // 没有输出

下面第一个单元下标是字符串,list()函数不能转为变量

list($a, $b, $c) = array('first'=>'one', 'two', 'three');

// print_r(array('first'=>'one', 'two', 'three')); // Array ( [first] => one [0] => two [1] => three )

echo '<br/>';

echo $a,'-<br/>'; // two-
echo $b,'-<br/>'; // three-
echo $c,'-<br/>'; // -        没有输出,只有一个标记" - "

可以只接收数组的第一个单元、第二个单元

list($a, $b) = array('one', 'two', 'three');

echo $a,'<br/>'; // one
echo $b,'<br/>'; // two

中间空出来,只接受数组的第一个和最后一个

list($a, , $c) = array('one', 'two', 'three');

echo $a,'<br/>'; // one
echo $c,'<br/>'; // three

list()函数用的地方非常多

// explode分隔字符串后,返回的是数组
$str = 'hello_world';

list($name, $pro) = explode('_', $str);

echo $name,'<br/>';
echo $pro,'<br/>';

list()按照从左到右的顺序接收数组单元

list($a, $b) = array(1 => '第一个单元', 'value' => '第一个单元', 0 => 'one', 'key' => 'one' );

echo $a,'<br/>'; // one
echo $b,'<br/>'; // 出不来


each()函数

1. each()函数参数是一个数组作,返回值也是一个数组

2. each只处理当前的元素(默认当前元素是数组的第一个元素,然后指针指向第一个),将当前元素转为数组信息,处理完后,指针向下一个元素移动

3. 如果指针已经在结束位置了,在使用each()获取元素,返回false


each()函数返回的值是一个数组,该数组有固定四个元素,而且下标也是固定(1, value, 0, key)

1 和 value 代表值

0 和 key   代表下标

$arr = ['one'=>'第一个单元', '第二个单元', '第三个单元'];

$res = each($arr);

print_r($res);

/***
Array
(
    [1] => 第一个单元
    [value] => 第一个单元
    [0] => one
    [key] => one
)
***/

echo $res['value'],'<br/>'; // 第一个单元

echo $res[1],'<br/>'; // 第一个单元

echo $res[0],'<br/>'; // one

echo $res['key'],'<br/>'; // one

将当前元素转为数组信息,每一次执行完后,指针向下一个元素移动

$arr = ['one'=>'第一个单元', '第二个单元', '第三个单元'];

// 第一次执行
$res = each($arr);
echo $res['value'],'<br/>'; // 第一个单元
echo $res[1],'<br/>'; // 第一个单元
echo $res[0],'<br/>'; // one
echo $res['key'],'<br/>'; // one

// 第二次执行
$res = each($arr);
echo $res['value'],'<br/>'; // 第二个单元
echo $res[1],'<br/>'; // 第二个单元
echo $res[0],'<br/>'; // 0
echo $res['key'],'<br/>'; // 0

// 第三次执行
$res = each($arr);
echo $res['value'],'<br/>'; // 第三个单元
echo $res[1],'<br/>'; // 第三个单元
echo $res[0],'<br/>'; // 1
echo $res['key'],'<br/>'; // 1


// 再往后处理,返回布尔值false
var_dump($res = each($arr)); // bool(false)

这就是each()的全部语法,他就这个作用

单纯使用each()没有什么意义,但是和list、while循环配合就有意义了

list(), each(), while循环,这三个配合起来遍历数组 

首先while循环和each配合

$arr = ['one'=>'第一个单元', '第二个单元', '第三个单元'];

while($tmp = each($arr)){
	print_r($tmp);
	echo '<br/>';
}

/***
Array ( [1] => 第一个单元 [value] => 第一个单元 [0] => one [key] => one )
Array ( [1] => 第二个单元 [value] => 第二个单元 [0] => 0 [key] => 0 )
Array ( [1] => 第三个单元 [value] => 第三个单元 [0] => 1 [key] => 1 )
***/

历出数组的下标和值

$arr = ['one'=>'第一个单元', '第二个单元', '第三个单元'];

while($tmp = each($arr)){
	echo "{$tmp['key']} : {$tmp['value']}<br/>";
}

/***
one : 第一个单元
0 : 第二个单元
1 : 第三个单元
***/

将数组结构转成变量,就要用到list()函数,数组中有几个单元,list()中就用几个参数

each()函数返回的是数组,有索引下标、关联下标,而且下标是从0开始

list()里面写两个变量,变量$key接收索引[0],变量$value接收索引[1],把键和值转成变量,循环里操作的就是变量了

$arr = ['one'=>'第一个单元', '第二个单元', '第三个单元'];

while(list($key, $value) = each($arr)){
	echo "$key : $value<br/>";
}

/***
one : 第一个单元
0 : 第二个单元
1 : 第三个单元
***/

如果只要值不要键呢?把第一个$key省略掉,预留出位置

$arr = ['one'=>'第一个单元', '第二个单元', '第三个单元'];

while(list(, $value) = each($arr)){
	echo "$value<br/>";
}

/***
第一个单元
第二个单元
第三个单元
***/

foreach能做到的,这个组合也能做到,但是这个组合有一个弊端,什么弊端呢?

each()有一个特点,指针循环结尾,就返回false

所以第一次循环后,再循环的条件是false,后面的循环就根本不执行

$arr = ['one'=>'第一个单元', '第二个单元', '第三个单元'];

while(list($key, $value) = each($arr)){
	echo "$key => $value<br/>";
}

/***
one : 第一个单元
0 : 第二个单元
1 : 第三个单元
***/

while(list($key, $value) = each($arr)){
	echo "$key => $value<br/>";
}

while(list($key, $value) = each($arr)){
	echo "$key => $value<br/>";
}

怎么把数组指针移回去呢?

这里简单的说一下,用reset()函数

$arr = ['one'=>'第一个单元', '第二个单元', '第三个单元'];

while(list($key, $value) = each($arr)){
	echo "$key => $value<br/>";
}

reset($arr);

while(list($key, $value) = each($arr)){
	echo "$key => $value<br/>";
}

reset($arr);

while(list($key, $value) = each($arr)){
	echo "$key => $value<br/>";
}

/***
one => 第一个单元
0 => 第二个单元
1 => 第三个单元
one => 第一个单元
0 => 第二个单元
1 => 第三个单元
one => 第一个单元
0 => 第二个单元
1 => 第三个单元
***/

用这个组合,遍历表格

$group = [
			'groupName'=>'第三组',
			'groupPrice'=>'888元',
			['name'=>'Lin', 'age'=>'32', 'sex'=>'男', 'email'=>'lin@ruyic.com'],
			['name'=>'Zhu', 'age'=>'21', 'sex'=>'女', 'email'=>'Zhu@ruyic.com'],
			['name'=>'Yu', 'age'=>'34', 'sex'=>'男', 'email'=>'Yu@ruyic.com'],
			['name'=>'Li', 'age'=>'32', 'sex'=>'男', 'email'=>'lin@ruyic.com'],
			['name'=>'Zh', 'age'=>'41', 'sex'=>'女', 'email'=>'Zh@ruyic.com'],
			['name'=>'Y', 'age'=>'34', 'sex'=>'男', 'email'=>'Y@ruyic.com']
		 ];

echo '<table border="1" width="800" align="center">';
echo '<caption><h1>数组转为表格</h1></caption>';

while(list($key, $row) = each($group)){
	echo '<tr>';
	
	if(is_array($row)){
		
		while(list(, $col) = each($row)){
			echo "<td> $col </td>"; // 循环一次输出一列
		}
		
	}else{
		echo '<td colspan="4">'.$key.': '.$row.'</td>';
	}
	
	echo '</tr>';
}

echo '</table>';

这个组合效率上和foreach差不多,但使用复杂性上比foreach高

二、十八哥的课程笔记

数组中最重要的两个概念

1. key,键/key/index/索引/下标

   编号是数字时叫索引/index,字符时叫键(key)/下标

2. 值/value

数组的声明中,体现的是 键 与 值 的对应,数组就是"键值对"的集合

$stu = array('1', 'name'=>'张三', 'height'=>176, 'area'=>'衡山', 'grade'=>'高三');

print_r($stu); // Array ( [0] => 1 [name] => 张三 [height] => 176 [area] => 衡山 [grade] => 高三 )

1、数组的创建

创建数组的两种方式

数组最本质的是"键值对",重要的是把"键 与 值"的对应关系体现出来

初始化(直接赋值)的方式创建数组

$stu = null;

$stu['name'] = '张三';
$stu['height'] = 176;
$stu['area'] = '衡水';
$stu['grade'] = '高三';

print_r($stu); // Array ( [name] => 张三 [height] => 176 [area] => 衡水 [grade] => 高三 )

array()结构来创建

$stu = array('name'=>'李四', 'height'=>176, 'area'=>'衡水', 'grade'=>'高三');

print_r($stu); // Array ( [name] => 李四 [height] => 176 [area] => 衡水 [grade] => 高三 )

这两种方法都可以创建数组

虽然形式上不同,但他们本质上有"相通之处",

既,都是声明"键与值的对应"


有时候需要增加一个单元

初始化方式,便于运行中,临时增加一个单元

$stu = array('name'=>'李四', 'height'=>176, 'area'=>'衡水', 'grade'=>'高三');

$stu['waring'] = '晚不归宿';

print_r($stu); // Array ( [name] => 李四 [height] => 176 [area] => 衡水 [grade] => 高三 [waring] => 晚不归宿 )


数组创建,之懒人方式

声明数组时,不写键行不行?

可以的,这种情况下,键会从0开始,逐一自动增加

$flower = array('梅', '兰', '竹', '菊');

print_r($flower); // Array ( [0] => 梅 [1] => 兰 [2] => 竹 [3] => 菊 )

直接赋值的方式,只写值不写值,键会从0开始,逐一自动增加

$stars[] = '刘德华';
$stars[] = '张学友';
$stars[] = '郭富城';
$stars[] = '黎明';

print_r($stars); // Array ( [0] => 刘德华 [1] => 张学友 [2] => 郭富城 [3] => 黎明 )


马虎者的创建方式,有单元写了键,有的单元没写键

1). 如果指定了键,则以指定的为准

2). 如果没指定,则从0开始,逐一递增

$yan = array('name'=>'燕十八', 'age'=>28, 174, '安徽');

print_r($yan); // Array ( [name] => 燕十八 [age] => 28 [0] => 174 [1] => 安徽 )


如果没指定,则从0开始,逐一递增。这句话说的不够准确

手册上最官方的权威解释:

如果方括号没有给出键名,则取当前最大整数索引值,新键名将该值 + 1。

如果当前还没有整数索引,则键名为0,

如果指定的键名已经有值了,该值将被覆盖。


下面数组的键是各是多少?

$class[] = '张三';  // 0
$class[] = '李四';  // 1
$class[5] = '王五'; // 5
$class[] = '赵六';  // 6
$class[] = '郑七';  // 7

print_r($class); // Array ( [0] => 张三 [1] => 李四 [5] => 王五 [6] => 赵六 [7] => 郑七 )


如何来理解这句:如果指定的键名已经有值了,该值将被覆盖。

下面打印$butty是什么样呢?武藤兰覆盖了苍井空

$butty[] = '林志玲';  // key: 0
$butty[] = '苍井空';  // 被覆盖
$butty[1] = '武藤兰'; // key: 1
$butty[2] = '小泽';   // key: 2

print_r($butty); // Array ( [0] => 林志玲 [1] => 武藤兰 [2] => 小泽 )

上面三个例子,讨论出键值的增长关系。


看一个陷阱

删掉了一个单元,键的增长不受影响,新增的单元的键继续往上增加

$arr = array('春', '夏', '秋', '冬');

print_r($arr); // Array ( [0] => 春 [1] => 夏 [2] => 秋 [3] => 冬 )

unset($arr[3]); // 删除最后一个单元 "冬"

echo '<br/>';
print_r($arr); // Array ( [0] => 春 [1] => 夏 [2] => 秋 )


/**
 * 最后一个单元"冬",被删除了
 * 再增加一个单元,新增单元的键是多少?
 * 0 1 2 4
 *
 */

$arr[] = '季节'; // 新增一个单元 "季节"

echo '<br/>';
print_r($arr); // Array ( [0] => 春 [1] => 夏 [2] => 秋 [4] => 季节 )

2、数组的操作


通过"键"读取一个单元的值,在js语言里面和C语言里面,数组是不能用字符串来做键(key)的,但是在PHP里面数组非常灵活

$arr = array('person', 'age'=>28, 'height'=>176);

echo $arr[0],'<br/>'; // person

echo $arr['age']; // 28

数组的一个单元,能容纳什么类型的值?

$class['stuOne'] = array('name'=>'张三', 'age'=>28);

print_r($class); // Array ( [stuOne] => Array ( [name] => 张三 [age] => 28 ) )


/***
Array
(
    [stuOne] => Array
        (
            [name] => 张三
            [age] => 28
        )
)
***/


// 打印内层二维数组中,第二个数组的单元
echo '<br/>',$class['stuOne']['age']; // 28

一般超过二维的,叫"多维数组"

如何给数组增加一个单元?增加非常简单,直接赋值就行了,可以指定键,也可以不指定键

$arrAdd = array('春', '夏');

$arrAdd[] = '秋';
$arrAdd[] = '冬';

print_r($arrAdd); // Array ( [0] => 春 [1] => 夏 [2] => 秋 [3] => 冬 )

如何修改数组中一个单元的值?指定要修改的单元,并赋值就可以了

$arrEdit = array('春', '夏', '秋', '冬');

$arrEdit[2] = 'autumn';
$arrEdit[3] = 'winter';

print_r($arrEdit); // Array ( [0] => 春 [1] => 夏 [2] => autumn [3] => winter )

如何删掉一个数组的单元?使用unset()函数删除

$arrDel = array('春', '夏', '秋', '冬');

print_r($arrDel); // Array ( [0] => 春 [1] => 夏 [2] => 秋 [3] => 冬 )

unset($arrDel[3]); // 删除下标是[3]的单元 "冬""

echo '<br/>';
print_r($arrDel); // Array ( [0] => 春 [1] => 夏 [2] => 秋 )

PHP语言非常灵活

在C语言中,js中,JAVA中,数组的索引只能是数字,而在PHP中,KEY/Index可以是字符串,也可以是数字

如果索引是纯数字称为"索引数组",否则称之为"关联数组"

什么栈、列表、队列、list,在PHP中一个数组搞定。

3、遍历数组

for循环遍历数组

默认情况下,数组的键从0开始,逐一递增,有规律可循环

count()函数计算数组的单元个数。数组的最大索引值,是数组的单元个数 - 1

$arr = array('春', '夏', 'autumu', 'winter', '雨');

for($i = 0, $len = count($arr); $i < $len; $i++ ){

	echo $arr[$i],'~<br/>';

}


/***
春
夏
autumu
winter
雨
***/

优化一下for循环的细节,提告运行效率

$arr = array('春', '夏', 'autumu', 'winter', '雨');

for($i = 0, $len = count($arr); $i < $len; $i++ ){

	echo $arr[$i],'<br/>';

}

foreach方式遍历数组

$arr = array(3=>'春', 2=>'夏', 5=>'秋', 9=>'冬');

// foreach是怎么工作的?
foreach($arr as $key=>$value){ // 循环数组的每个单元,每一次循环时,把当前循环的单元"键"赋给$key、"值"赋给$value

	echo $key,'~',$value,'<br/>';

}

/***
3~春
2~夏
5~秋
9~冬
***/

如果最后在foreach循环外面,再打印$key、$value,输出的是什么

foreach($arr as $key=>$value){

	echo $key,'~',$value,'<br/>';

}

echo $key,'=',$value; // 输出的是数组最后一对键值:9 = 冬

停留在最后一次$key和$value赋值的状态

foreach第二种用法,循环只取数组的值

$arr = array(3=>'春', 2=>'夏', 5=>'秋', 9=>'冬');

foreach($arr as $value){ // 循环数组的每个单元,把单元的值赋给$value

    echo $value,'<br/>';

}

/****
春
夏
秋
冬
***/

如果只要数组的键key,不想要数组的值呢?

这样不行,因为指定变量$key和变量$value是我们自己定义的临时变量,用来放读出来的键和值

就算变量名是$key,语法也是把数组的值取出来赋给了$key

$arr = array(3=>'春', 2=>'夏', 5=>'秋', 9=>'冬');

foreach($arr as $key){

	echo $key,'<br/>'; // 打印的还是值

}

/***
春
夏
秋
冬
***/

可以这样取得单独键

$arr = array(3=>'春', 2=>'夏', 5=>'秋', 9=>'冬');

foreach($arr as $key=>$value){

	echo $key,'<br/>';

}

/***
3
2
5
9
***/


直播同学让燕十八老师看的面试题

这个题牵扯到运算符优先级的问题

1). if($a = 7 && $b == 7) 

                7 && $b  优先级高,优先发挥的作用

2). 得到的$a是true,true++还是true

3). 索引$a输出的是 1

$a = 5;

$b = 7;

if($a = 7 && $b == 7){
	$a ++;
	$b ++;
}

echo $a, '~' ,$b; // 1~8

顺便练习一个题

$b = 5;

if($a = 8 && $b = 9){

    $a = $a + 1;

    $b = $b + 1;

}

echo $a, '~', $b; // 2~10

4、数组的游标操作

游标操作在开发中没有foreach用的频繁,但是通过游标操作,可以更加深入解底层,去了解数组是怎么循环的。

数组有N个单元,同时只能操作一个单元

比如在循环中,也是循环出一个单元,读取一个单元的,如果读取完第一个单元,下次再来读取时,怎么记住该读取第二个单元了呢?

在数组内部,有一个指针,指针指着某一个单元。每循环一个单元,指针往尾部移动


数组的游标操作主要有下面几个函数


current英语里有"当前的"意思,该函数是取出,数组内部指针,指向当前单元的"值"。

一个数组刚刚定义,指针指向第0个单元,执行current($arr)打印的是第0单元的值

第二次执行current($arr)打印的和第一次一样,因为数组下标没有完后移动

$arr = array('春', '夏', '秋', '冬');

echo current($arr),'<br/>'; // 春

echo current($arr),'<br/>'; // 春

/**
 * key函数是,取出数组内部指针,指向的单元"键"
 * 执行两次key($arr)函数,打印的都是 0
 * 因为此时指针还是指向第0个单元
 *
 */

echo key($arr),'<br/>'; // 0

echo key($arr),'<br/>'; // 0


next英语里有"下一个"的意思,把数组内部指针往尾部移动一个单元

执行current($arr),再执行key($arr),指针继续往后走

$arr = array('春', '夏', '秋', '冬');

next($arr);
echo current($arr),'<br/>'; // 夏
echo key($arr),'<br/>'; // 1

next($arr);
echo current($arr),'<br/>'; // 秋
echo key($arr),'<br/>'; // 2

next($arr);
echo current($arr),'<br/>'; // 冬
echo key($arr),'<br/>'; // 3

/**
 * next($arr)再往后走
 * current($arr) 读不到值,返回布尔类型false
 * key($arr) 下标返回空null
 *
 */

next($arr);
var_dump(current($arr)); // bool(false)
var_dump(key($arr)); // NULL

手册:

mixed current( array $array );

每个数组中都有一个内部的指针指向他"当前的"单元,初始时指针指向数组中的第一个单元

current()函数返回内部指针,指向的数组单元的值,并不移动指针。

如果内部指针指向超过单元列表的末端,current()返回FALSE

如果数组包含空的单元(0或"")current()函数也返回FALSE。

要正确的遍历可能含有空单元的数组,用each()函数

miexd next( array $array );

返回数组指针,指向下一个单元的值,最后一个单元在往后时返回FALSE

如果数组包含空的单元"",或单元的值是0,next()函数也返回FALSE。

要正确的遍历可能含有空单元"",或单元的值为0的数组,参见each()函数


能不能从后到前打印出来?

既,先把指针指向数组最后,然后逐步往前移动指针

默认指针指向第0个单元

end()  该函数把指针指向数组的最后一个单元

prve() 从后向前移动指针

$arr = array('春', '夏', '秋', 'winter');

end($arr); // 将数组指针指向最后

echo current($arr),'<br/>';  // winter
echo key($arr),'<br/>'; // 3

prev($arr); // 把指针往前移动
echo current($arr),'<br/>';  // 秋
echo key($arr),'<br/>'; // 2

prev($arr); // 把指针往前移动
echo current($arr),'<br/>';  // 夏
echo key($arr),'<br/>'; // 1

prev($arr); // 把指针往前移动
echo current($arr),'<br/>';  // 春
echo key($arr),'<br/>'; // 0

prev($arr); // 把指针往前移动
echo current($arr),'<br/>';  // 什么都看不到
echo key($arr),'<br/>'; // 什么都看不到


/**
 * 不是什么都看不到
 * 因为false打印出来是空字符串
 * null打印出来还是空字符串
 * 用var_dump打印
 *
 */

var_dump(current($arr));  // bool(false) 

var_dump(key($arr)); // NULL


利用next()和prve()来循环数组

reset()函数可以重置数组指针

$arr = array('春', '夏', '秋', 'winter');

reset($arr);

echo current($arr),'<br/>';  // 春
echo key($arr),'<br/>'; // 0

//连续两次next()
next($arr);
next($arr);

echo current($arr),'<br/>';  // 秋
echo key($arr),'<br/>'; // 2

reset($arr); // 执行reset()

echo current($arr),'<br/>';  // 春
echo key($arr),'<br/>'; // 0


现在有六个函数:curentt()、key()、next()、prve()、reset()、ned()

单独用for循环,是没法处理关联数组的,但是结合游标操作之后,就可以循环处理了

$arr = array('name'=>'张三', 'age'=>28, 'height'=>176, 'area'=>'山西');

for(; current($arr); next($arr)){

    echo key($arr),'~',current($arr),'<br/>';

}

这里只是为了练习游标操作,实际开发中用foreach

游标处理数组非常灵活

打印一个单元,跳过过一个单元,再打印……怎么实现?

写两次next()

$arr = array('荣', '耀', '只', '属', '于', '真', '正', '上', '场', '的', '人');

for(; current($arr); next($arr),next($arr)){

	echo key($arr),'~',current($arr),'<br/>';

}

/***
比foreach还灵活

0~荣
2~只
4~于
6~正
8~场
10~人
***/

走两步退一步,怎么用游标实现

$arr = array('荣', '耀', '只', '属', '于', '真', '正', '上', '场', '的', '人');

$flag = true;

// reset($arr); // 重置数组

for(; current($arr); ){
	
	echo key($arr),'~',current($arr),'<br/>';
	
	if($flag){
		next($arr);
		next($arr);
		$flag = false;
	}else{
		prev($arr);
		echo key($arr),'~',current($arr),'<br/>';
		$flag = true;
	}
}

foreach不是函数,是语言结构

当foreach开始执行时,数组内部指针会自动指向第一个单元。这意味着在foreach循环之前系统自动调用reset()

执行两次foreach都是从数组开头开始打印

$arr = array('a', 'b', 'c', 'd');

foreach($arr as $v){

	echo $v,'<br/>';

}

foreach($arr as $v){

	echo $v,'<br/>';

}

总之,foreach在运行前会自动reset()重置数组,因此foreach不会受上一次的影响

$arr = array('a', 'b', 'c', 'd');

echo current($arr),'<br/>'; // a

foreach($arr as $v){
	echo $v,'<br/>';
}

// PHP5:foreach结束后,并没有马上帮我们把指针初始化
//var_dump(current($arr)); // bool(false)  ,PHP5

// PHP7执行完后马上把游移回了数组头一位
var_dump(current($arr)); //string(1) "a"   ,PHP7

看一个小陷阱

1). 第一个单元的值为0,

2). 0转成布尔值为假false,

3). 因此for循环直接跳出了

所以下面的循环没有任何输出

$arr = array(0, 1, 2, 3, 4);

for( ;current($arr); next($arr)){

	echo current($arr),'<br/>';

}

再看下面

for循环遇到值为0的时就结束

因此只打印出-3、-2、-1,当指向0的时候,0为假for循环就退出了

如果数组某个单元的值为空字符串""、0、false、null,都将导致循环退出

解决方法each()函数

echo '<hr/><br/><br/><br/>';

$arr = array(-3, -2, -1, 0, 1, 2, 3, 4);

for( ;current($arr); next($arr)){
	echo current($arr),'<br/>';
}

/***
-3
-2
-1
***/

5、list()与each()

each()函数

each在英语里有"每一个"的意思,each()函数就是用来遍历数组用的,他能把数组中的每一个单元拿出来,而且该函数拿出来的数组单元值非常有特点。

作用:是把指针,指向的当前单元的信息组成一个数组返回,并且把指针向数组尾部移动一次。

特点:返回一个数组,有四个单元,放了两样信息,当前单元的键和值,返回数组的四个单元格式(1、value、0、key)是固定的 。

1        值

value 值

0       当前指针

key   当前指针

$arr = array('东', '邪', '西', '毒');


print_r(each($arr)); // Array ( [1] => 东 [value] => 东 [0] => 0 [key] => 0 )

/***
 * 第一次执行each()
 * 第一个单元的key是0,value是"东"
 *
 * Array
 * (
 *    [1] => 东       值
 *    [value] => 东   值
 *    [0] => 0        当前指针
 *    [key] => 0      当前指针
 * )
 *
 * [1]和[value]是值
 * [0]和[key]  是键
 * 关联和索引各一次
 *
 */




print_r(each($arr)); //  Array ( [1] => 邪 [value] => 邪 [0] => 1 [key] => 1 )
echo '<br/>';

/***
 * 第二次执行
 * Array
 * (
 *    [1] => 邪
 *    [value] => 邪
 *    [0] => 1
 *    [key] => 1
 * )
 *
 */




print_r(each($arr));
echo '<br/>';
print_r(each($arr));
echo '<br/>';

/***
 * 再执行两次each($arr),指针再往后走二次
 *
 * Array
 * (
 *   [1] => 西
 *   [value] => 西
 *   [0] => 2
 *   [key] => 2
 * )
 *
 * Array
 * (
 *   [1] => 毒
 *   [value] => 毒
 *   [0] => 3
 *   [key] => 3
 * )
 *
 */




/**
 * 再往后执行each($arr)就看不到什么东西了
 * 用var_dump(each($arr))查看,返回bool(false)
 *
 */

echo '<br/>';
print_r(each($arr)); 

echo '<br/>';
var_dump(each($arr)); // bool(false)

总结:

each()函数取出指针所指单元的键和值,组合成一个数组返回,并把指针向后移动,如果取不出单元返回false


根据eacha()函数的特点,用while循环遍历数组

如果取出单元,则返回1、value、0、key四个固定格式的数组

如果指针超过界限,返回false,自然while结束

$arr = array(-3, -2, -1, 0, 1, 2, 3);

while($ceil = each($arr)){

	//echo $ceil[0], '=>', $ceil[1],'<br/>';
	echo $ceil['key'], '=>', $ceil['value'],'<br/>';

}


list()函数

each()函数经常和list()函数一起用

list()函数是复合赋值语句,可以一次性为多个变量赋值

先看下面常见的操作,把数组中的单元赋给多个变量,然后在打印变量

$arr = array('东', '南', '西', '北');

$east = $arr[0];
$south = $arr[1];
$west = $arr[2];
$north = $arr[3];

echo $east,'<br/>'; // 东
echo $south,'<br/>'; // 南
echo $west,'<br>'; // 西
echo $north,'<br>'; // 北

list()函数可以一次性的给多个变量赋值

echo '<br/>';

$arr = array('春', '夏', '秋', '冬');

list($spring, $summer, $autumn, $winter) = $arr;

echo $spring,'<br/>'; // 春
echo $summer,'<br/>'; // 夏
echo $autumn,'<br/>'; // 秋
echo $winter,'<br/>'; // 冬

list()函数赋值过程是怎么发生的呢?下面为什么没有打印出变量$a呢?

list($a, $b, $c) = array(2=>'赵', 3=>'钱', 1=>'孙'); // Notice: Undefined offset: 0 in

if(isset($a)){
	echo $a,'<br/>';
}else{
	echo '没有变量$a<br/>'; // 没有变量$a
}

if(isset($b)){
	echo $b,'<br/>'; // 孙
}else{
	echo '没有变量$b<br/>';
}

if(isset($c)){
	echo $c,'<br/>'; // 赵
}else{
	echo '没有变量$c<br/>';
}


list()函数是如何工作的?

因为list能给多个变量赋值,既、把数组的多个单元分别赋值给多个值。

那么,自然要注意一个最重要的地方,数组的哪个单元对应赋给哪个变量。


怎么样对应的呢?

在list($a, $b, $c)中变量按逗号隔开的顺序,从左到右分别对应,右侧数组$arr[0]、$arr[1]、$arr[2]

如果需要对应右侧的$arr[x]不存在怎么办?

依然先,对应能对应上的,不存在的当NUL来处理。


因此

$a 映射 $arr[0]

$b 映射 $arr[1]

$c 映射 $arr[2]


映射完成就该赋值了,赋值的过程和映射的顺序是反着的,是从右向左赋值

$c = $arr[2];

$b = $arr[1];

$a = $arr[0];


打印结果

$c = '赵';

$b = '孙';

$a = NULL; // $arr[0]不存在


$arr[1], , $arr[2] 注意这里有两个逗号

list($arr[0], $arr[1], , $arr[2]) = array(3=>'赵', 1=>'钱', 5=>'孙', 2=>'李', 0=>'燕');

print_r($arr); // Arrar([0]=>燕 [1]=>钱 [2]=>赵)

分析:

1).先从左到有映射,分配赋值的过程

$arr[0] 映射 array[0] 燕

$arr[1] 映射 array[1] 钱

多个一个逗号,往后跳一个

$arr[2] 映射 array[3] 赵

2).分配完,从右往左赋值

$arr[2] = '赵';

$arr[1] = '钱';

$arr[0] = '燕';

PHP5 数组打印是按创建的顺序

PHP7 Array ( [0] => 燕 [1] => 钱 [2] => 赵 )


each()函数加上list()函数,自己写一个模拟foreach函数,foreach是语法结构

$arr = array(3=>'赵', 1=>'钱', 5=>'孙', 2=>'李', 0=>'燕');

while(list($key, $value) = each($arr)){

	echo $key, '~', $value, '<br/>';

}

/***
3~赵
1~钱
5~孙
2~李
0~燕
***/

封装一个函数for_each($arr, $value)

$arr = array(3=>'赵', 1=>'钱', 5=>'孙', 2=>'李', 0=>'燕');

function for_each($arr){

	while($tmp = each($arr)){

        list($key, $value) = $tmp;
		echo $key, $value,'<br/>';

    }

}

for_each($arr);

优化代码

$arr = array(3=>'赵', 1=>'钱', 5=>'孙', 2=>'李', 0=>'燕');

function for_each2($arr){

	while(list($key, $value) = each($arr)){

        echo $key, $value,'<br/>';

    }

}

for_each2($arr);

6、数组的下标怎么写

数组的下标怎么写

1、整形(数字)的索引值,不必加单/双引号。比如['1']加了单/双引号,则需要隐式的把字符串"1"转换成整型1,会影响效率。

2、字符串型的下标,必须加单双引号。

3、加单引号还是双引号,单引号的解析速度远比双引号块,所以优先加双引号


如果字符串型下标不加单/双引号,虽然打印出了值,但出现警告Warning/注意Notice信息

/**
 * 虽然打印出了值(夏天)但出现提示警告信息
 * PHP不同版本的信息有点小区别
 * PHP7.3 Warning: Use of undefined constant ……
 * PHP5.3 Notice: Use of undefined constant ……
 *
 */

$arr = array(1=>'季节', 'spring'=>'春天', 'summer'=>'夏天', 'autumn'=>'秋天', 'winter'=>'冬天');

echo $arr[summer]; // PHP7 Warning: Use of undefined constant ……
                   // 夏天


Notice是"注意"的意思

手册:索引(搜:errer reporting) -> error_reporting -> int error_reporting([int $leve1])

error_reporting(E_ALL & ~ E_NOTICE); 这句的意思是把Notice级别的错误信息屏蔽掉 

error_reporting(E_ALL & ~ E_WARNING);同理,屏蔽warning级别的信息


屏蔽Notice/warning级别的错误信息,字符串下标没有加引号也能输出值

error_reporting(E_ALL & ~ E_NOTICE); 
error_reporting(E_ALL & ~ E_WARNING);

$arr = array(1=>'季节', 'spring'=>'春天', 'summer'=>'夏天', 'autumn'=>'秋天', 'winter'=>'冬天');

echo $arr[summer]; // 夏天

继续探究,下面做两步

1). 字符串类型的下标[summer]依然不加单/双引号

2). 定义一个常量,常量名:summer,常量值:season

// error_reporting(E_ALL & ~ E_NOTICE); 
// error_reporting(E_ALL & ~ E_WARNING);

$arr = array(1=>'季节', 'spring'=>'春天', 'summer'=>'夏天', 'autumn'=>'秋天', 'winter'=>'冬天');

define('summer', 'season'); // 定义一个常量summer

echo $arr[summer]; // Notice: Undefined index: season in…… 

/**
 * 打开,屏蔽Notice/warning级别的错误信息
 * PHP7输出:Notice: Undefined index: season in……
 * PHP5不输出任何内容
 *
 * 注释,屏蔽Notice/warning级别的错误信息
 * PHP5   Notice: Undefined index: season in…… 
 * 
 */

注意信息:Notice: Undefined index: season…… 没有定义的索引season

提示说明PHP没有找数组的[summer]下标,而是找的是常量[season]

说明把$season[summer] -> 引用的是$season[season],没有[season]单元所以报Notice

总结规律:

$season[summer]没有加引号(单引或双引),理解成常量名summer,并且按照常量值来做下标$arr[season]

如果没有summer常量,再次把summer当成字符串的下标来处理。

不加单/双引号,流程上先理解成常量,如果没有常量,再当做字符串,效率上非常低。

字符串需要加单双引号,避免因常量定义而产生错误


如果在数组里面定义一个下标的键名为season,常量summer的值也是season,常量的值作为下标的键可以打印出数组对应的值。

说明不加单双引号,字符串下标确实是当先当做常量来解析,没有这个常量再当中字符串

$arr = array('season'=>'季节', 'spring'=>'春天', 'summer'=>'夏天', 'autumn'=>'秋天', 'winter'=>'冬天');

define('summer', 'season'); // 定义一个常量summer

echo $arr[summer]; // 季节


1627097211


Leave a comment 0 Comments.

Leave a Reply

换一张