PHP之数组
数组
PHP中的数组是一个有序映射(一种把values关联到keys的类型),或者称之为有序字典,Objective-c的数组的下标只能是数字,且元素必须是对象类型,而字典是一个映射,但字典是无序的且其键名不能是数字.这就很有意思.
数组一般作为容器类变量,用来承载多个变量或常量.
可以把数组分为三种类型:
- 数值数组|索引数组(键名为数值类型的数组)
- 关联数组(带有指定的键的数组,每个键关联一个值)
- 多维数组(包含一个或多个数组的数组)
注:PHP 实际并不区分索引数组和关联数组
数组的创建
空数组
$arr = array();
数值数组
用逗号,
来分隔每个元素,用=>
来连接key和value,最后一个元素之后的逗号可以省略,键(key)可以是数值或者string,值(value)可以是任意类型的值
$arr = array('item','user',2,false,null);
关联数组
,指定键名
$arr = array('key1'=>'value1',2=>false,'3'=>null);
二维数组
二维索引+索引
echo '<h4>二维索引+索引</h4>';
$arr = array(
array(1,'zhangsan'
),
array(2,'lisi','xxx','222333'
)
);
print_r($arr);
二维索引+关联
echo '<h4>二维索引+关联</h4>';
$arr = array(
array('id'=>1,
'username'=>'zhangsan'
),
array('id'=>2,
'username'=>'lisi'
)
);
print_r($arr);
二维关联+索引
echo '<h4>二维关联+索引</h4>';
$arr = array(
'users' =>array('king','queen','李四'),
'ages'=>array(13,24,22)
);
print_r($arr);
二维关联+关联
echo '<h4>二维关联+关联</h4>';
$arr = array(
'user1' =>array(
'name'=>'king',
'age'=>22,
'id'=>'1352222'
),
'user2'=>array(
'name'=>'allen',
'age'=>23,
'id'=>'145222'
)
);
print_r($arr);
新的定义方式[] PHP5.4起
用[]来代替array()
$arr = ['a','b','foo'=>'bar','name'=>'xiaosi'];
[]可以动态的修改数组
$arr[] = 'user';
$arr[] = 'sex';
$arr[] = 'age';
$arr['class']=32;
print_r($arr);
/*
Array
(
[0] => user
[1] => sex
[2] => age
[class] => 32
)
*/
[],{}访问数组
通过array[key]来访问,{}和[]相同
$arr = ['name'=>'xix','age'=>23,'sex'=>true];
var_dump($arr['name']);
var_dump($arr{'name'});
range(),compact()快速创建
range()创建索引数组
1.快速创建数组 range(参数1,参数2,参数3)是下标连续的,参数1是起始位置,参数2是结束位置,参数3是步长(可省略)
$arr= range(1, 10);
print_r($arr);
2.手动指定步长的数组,步长的正负并不影响,因为参数1和参数2的大小决定了步长的符号
$arr=range(2, -4,2);
print_r($arr);
3.参数1和参数2会自动转为整形,比如false=0,true=1,'2'=2,若两个都可以转化为ASCII码,则转换为ASCII,比如('2','a')时,=>(2,0),而('>','B')则按照ASCII进行
$arr=range('>', 'B');
print_r($arr);
4.range()其实同for循环动态创建索引数组,chr()将ASCII转成对应字符
for ($i=97; $i<=122 ; $i++){
$arr1[] = chr($i);
}
print_r($arr1);
compact()创建关联数组
1.compact()
$username ='allen';
$age=24;
$email='2033444888@qq.com';
$arr = array(
'username' => $username ,
'age'=>$age,
'email'=>$email
);
print_r($arr);
echo "方式2:[]动态创建数组<br/><br/>";
$userInfo['username']=$username;
$userInfo['age']=$age;
$userInfo['email']=$email;
print_r($userInfo);
2.compact()创建,通过compact()创建数组的时候,只能写已经存在的变量的名称,不需要加$,名称就是对应的键名,然后会寻找该名称的变量名,如果变量名不存在,是没有对应的键值对的
$username ='allen';
$age=24;
$email='2033444888@qq.com';
$a=12;
$userInfo1=compact('username','age','email','a','b','c');
//不存在 'b','c';
print_r($userInfo1);
define,const定义常量数组
1.定义常量数组,const在php5.6之后可以定义常量
const ARR1 = array('优秀','良好','及格','不及格');
print_r(ARR1);
const ARR2 = [
'timeInterval'=>3.0,
'content-type'=>'text/html',
'content-length'=>2457,
'accept-lanuage'=>'en'
];
print_r(ARR2);
2.通过define定义常量数组
define('TEST1', array('a','b','c'));
print_r(TEST1);
define('TEST2', ['2',true,344]);
print_r(TEST2);
define('CUSTOM_UPLOAD_ERRORS', [
'ext_error'=>"上传文件扩展名不符合规格",
'maxsize_error'=>"上传文件大小不符合规格",
'time_error'=>"上传超时"
]
);
print_r(CUSTOM_UPLOAD_ERRORS);
echo "<br/>";
echo CUSTOM_UPLOAD_ERRORS['ext_error'];
数组的使用
键转换规则
当键不是integer或string类型的数据,会发生强制转换(优先转换为整形,其次转为字符串类型):
- 包含合法整型值的字符串会被转换为整形, 比如'8'=>8,'08'不是一个合法的整型值,不会发生强制转换.
- 浮点数->整形,小数部分直接舍去,不是四舍五入
- 布尔类型->整形 true->1,false->0
- null转换为空字符串,null->''
- 数组和对象不能当做键名
测试键名
$arrays = array(
3 =>a ,
'username'=>'zhansan',
5.6 =>"浮点数转为整数", //5
5=>'f',//覆盖上一个
true=>'true=1',
false=>'false=0',
null=>'\'\'' //null = ''
);
var_dump($arrays);
/*
array(6) {
[3]=>
string(1) "a"
["username"]=>
string(7) "zhansan"
[5]=>
string(1) "f"
[1]=>
string(6) "true=1"
[0]=>
string(7) "false=0"
[""]=>
string(2) "''"
}
*/
如果对给出的值没有指定键名,则取当前最大的整数索引值,而新的键名将是该值加一。如果指定的键名已经有了值,则该值会被覆盖。如:
- 键名重复,后定义的会覆盖前面的值.
- 新添加的元素没有指定键名,它的下标为已有下标最大值加一(已有下标不全为负数)
- 如果已有下标都为负数,新添加元素的下标从0开始.
不全为负数
$arr = array(
'a',
'b',
18 => 'd',
'c',
'g'
);
var_dump($arr);
/*
array(5) {
[0]=>
string(1) "a"
[1]=>
string(1) "b"
[18]=>
string(1) "d"
[19]=>
string(1) "c"
[20]=>
string(1) "g"
}
*/
全为负数从0开始
$arr = array(
-11=>'a',
-12=>'b',
-3=>'c',
'g'
);
var_dump($arr);
/*
array(4) {
[-11]=>
string(1) "a"
[-12]=>
string(1) "b"
[-3]=>
string(1) "c"
[0]=>
string(1) "g"
}
*/
数组的解引用
自 PHP 5.4 起可以用直接对函数或方法调用的结果进行数组解引用,之前只能通过一个临时变量。
自 PHP 5.5 起可以直接对一个数组原型进行数组解引用.
function getArray() {
return array(1, 2, 3);
}
// on PHP 5.4
$secondElement = getArray()[1];
// previously
$tmp = getArray();
$secondElement = $tmp[1];
// or
list(, $secondElement) = getArray();
数组的增删改查
- 查询: $array[key],$array{key}
- 增: $array[key] = $value,key不存在
- 改: $array[key] = $newValue,key存在,覆盖
- 删: unset($array[key]);
$arr = array(5 => 1, 12 => 2);
$arr[] = 56; // This is the same as $arr[13] = 56;
// at this point of the script
$arr["x"] = 42; // This adds a new element to
// the array with key "x"
unset($arr[5]); // This removes the element from the array
unset($arr); // This deletes the whole array
array_values($array) 重建数组索引
对于索引数组,当我们删除其中的一个元素,但是还想其索引是连续的,可以使用array_values();对于关联数组,原有的key会被覆盖为数值
$a = array(1 => 'one', 2 => 'two', 3 => 'three','name'=>'zhangsan',"age"=> 12);
//删除一个元素
unset($a[2]);
//重建索引
$b = array_values($a);
print_r($b);
/*
Array
(
[0] => one
[1] => three
[2] => zhangsan
[3] => 12
)
*/
数组的个数count()
count — 计算数组中的单元数目,或对象中的属性个数,注意:非数组和对象类型的变量
$arr = range('a','z');
echo count($arr),'<br/>';
$var = 123; //1
echo count($var),'<br/>';
$var = null; //0
echo count($var),'<br/>';
$var = true; //1
echo count($var),'<br/>';
$var = false; //1
echo count($var),'<br/>';
数组的遍历
1.数组的遍历 普通的for循环 (对于下标不连续的不适用)
$arr = range('a','z');
for ($i=0; $i <25; $i++) {
echo $arr[$i],'<br/>';
}
2.foreach遍历数组,对象
//方式1:
foreach ($variable as $value) {
# code...
}
//方式2:
foreach ($variable as $key => $value) {
# code...
}
$arr = [
5=>'a',
12=>'b',
-123=>'c',
'age'=>20,
34=>'d',
'userName'=>'lisi',
];
foreach ($arr as $value) {
echo $value,'<br/>';
}
foreach ($arr as $key => $value) {
echo $key,' => ',$value,'<br/>';
}
echo $key,' _____ ',$value,'<br/>';
unset($key);
unset($value);
注意:最后变量$key和$value的是有值的,没有被销毁.
未销毁引用带来的错误
$arr = ['a','b','c','d'];
foreach ($arr as $key => &$value) {
$value = $value.'_'.$value;
echo $value.'<br/>';
}
print_r($arr);
var_dump($value);
echo "<hr/>";
foreach ($arr as $key => $value) {
echo $value.'<br/>';
print_r($arr);
}
echo "<hr/>";
print_r($arr);
foreach 通过值遍历时,操作的值是数组的副本 (有待考证~!!!!!)
猜想:如果是副本那么输出结果应该是数组的全部元素,但实际是最后一个元素没有输出,但不是副本吧,输出的结果也不符合,只能解释为 foreach 依赖内部数组指针,在循环中修改其值将可能导致意外的行为。
$arr = [1,'www','22',false];
foreach ($arr as $value) {
echo $value,'<br/>';
unset($arr[0]);
}
var_dump($arr);
/*
1
www
22
array(3) {
[1]=>
string(3) "www"
[2]=>
string(2) "22"
[3]=>
bool(false)
}
*/
在循环中改变数组 用&表示通过引用遍历,有更好的迭代性
$arr = [1,'www'];
//输出两个元素
foreach ($arr as $value) {
echo $value,'<br/>';
$arr[1] = 'b';
}
//打印结果
//1
//www
print_r($arr);
$arr = [1,'www'];
//输出三个元素
foreach ($arr as &$value) {
echo $value,'<br/>';
$arr[2] = 'b';
}
//打印结果
//1
//www
//b
print_r($arr);
二维数组的遍历
$users = [
['id'=>12223,'username'=>'queen','age'=>24],
['id'=>23333,'username'=>'allen','age'=>34],
['id'=>32222,'username'=>'crush','age'=>54],
['id'=>40001,'username'=>'queen3','age'=>52],
['id'=>00001,'username'=>'queen4','age'=>23],
['id'=>33331,'username'=>'queen5','age'=>98]
];
foreach ($users as $user) {
echo '编号: ',$user['id'],'<br/>';
echo '姓名:',$user['username'],'<br/>';
echo '年龄:',$user['age'],'<br/>';
}
PHP7中的foreach使用 :endforeach;
$arr = ['a','b','c'];
foreach ($arr as $key => $value):
echo $key,'----',$value,'<br/>';
endforeach;
foreach不改变内部数组的(current())指针
$arr = ['a','b',3,false];
foreach ($arr as $key => $value) {
var_dump(current($arr));
}
/*
string(1) "a"
string(1) "a"
string(1) "a"
string(1) "a"
*/
数组的类型转换
对于任意 integer,float,string,boolean 和 resource 类型,如果将一个值转换为数组,将得到一个仅有一个元素的数组,其下标为 0,该元素即为此标量的值。换句话说,(array)$scalarValue 与 array($scalarValue) 完全一样。
临时转换
$var = 123;
$res = (array)$var;
var_dump($res);
var_dump($var);
echo("<br/>");
echo("<br/>");
$var = 123.2222;
$res = (array)$var;
var_dump($res);
var_dump($var);
$var = true;
$res = (array)$var;
var_dump($res);
var_dump($var);
echo("<br/>");
echo("<br/>");
echo "<h4>null是转换成空数组</h4>";
$var = null;
$res = (array)$var;
var_dump($res);
var_dump($var);
echo "<hr/>";
永久转换settype
$var = 234;
settype($var, 'array');
var_dump($var);
如果一个 object 类型转换为 array,则结果为一个数组,其单元为该对象的属性。键名将为成员变量名,不过有几点例外:整数属性不可访问;私有变量前会加上类名作前缀;保护变量前会加上一个 '*' 做前缀。这些前缀的前后都各有一个 NULL 字符。这会导致一些不可预知的行为:
待添加
数组指针函数
1.key($array)得到当前指针所在的位置的键名,如果不存在返回null,current($array)得到当前指针所在位置的键值,如果不存在返回false
$users = ['name'=>'lisi','age'=>22,'class'=>'三年二班','score'=>127];
echo '当前指针位置的键名:',key($users),'<br/>';
echo '当前指针位置的键值:',current($users),'<br/>';
/*
*/
2.next($array):将数组指针向下移动一位,并且返回当前指针所在位置的键值,如果没有,返回false
$users = ['name'=>'lisi','age'=>22,'class'=>'三年二班','score'=>127];
echo next($users),'<br/>';
echo '当前指针位置的键名:',key($users),'<br/>';
echo '当前指针位置的键值:',current($users),'<br/>';
echo next($users),'<br/>';
echo '当前指针位置的键名:',key($users),'<br/>';
echo '当前指针位置的键值:',current($users),'<br/>';
echo next($users),'<br/>';
echo '当前指针位置的键名:',key($users),'<br/>';
echo '当前指针位置的键值:',current($users),'<br/>';
var_dump(next($users));
echo '当前指针位置的键名:',key($users),'<br/>';
echo '当前指针位置的键值:',current($users),'<br/>';
/*
22
当前指针位置的键名:age
当前指针位置的键值:22
三年二班
当前指针位置的键名:class
当前指针位置的键值:三年二班
127
当前指针位置的键名:score
当前指针位置的键值:127
bool(false)
当前指针位置的键名:
当前指针位置的键值:
*/
3.prev($array):将数组指针向上移动一位,并且返回当前指针所在位置的键值,如果没有,返回false
$users = ['name'=>'lisi','age'=>22,'class'=>'三年二班','score'=>127];
echo end($users),'<br/>';
echo prev($users),'<br/>';
echo '当前指针位置的键名:',key($users),'<br/>';
echo '当前指针位置的键值:',current($users),'<br/>';
echo prev($users),'<br/>';
echo '当前指针位置的键名:',key($users),'<br/>';
echo '当前指针位置的键值:',current($users),'<br/>';
echo prev($users),'<br/>';
echo '当前指针位置的键名:',key($users),'<br/>';
echo '当前指针位置的键值:',current($users),'<br/>';
echo prev($users),'<br/>';
echo '当前指针位置的键名:',key($users),'<br/>';
echo '当前指针位置的键值:',current($users),'<br/>';
/*
127
三年二班
当前指针位置的键名:class
当前指针位置的键值:三年二班
22
当前指针位置的键名:age
当前指针位置的键值:22
lisi
当前指针位置的键名:name
当前指针位置的键值:lisi
当前指针位置的键名:
当前指针位置的键值:
*/
4.reset($array):将数组指针移动到数组开始,并且返回当前指针位置所在位置的键值,若果没有,返回false
$users = ['name'=>'lisi','age'=>22,'class'=>'三年二班','score'=>127];
echo reset($users),'<br/>';
echo '当前指针位置的键名:',key($users),'<br/>';
echo '当前指针位置的键值:',current($users),'<br/>';
/*
lisi
当前指针位置的键名:name
当前指针位置的键值:lisi
*/
5.end($array):将数组指针移动到数组末尾,并且返回当前指针位置所在位置的键值,若果没有,返回false.
$users = ['name'=>'lisi','age'=>22,'class'=>'三年二班','score'=>127];
echo end($users),'<br/>';
echo '当前指针位置的键名:',key($users),'<br/>';
echo '当前指针位置的键值:',current($users),'<br/>';
/*
127
当前指针位置的键名:score
当前指针位置的键值:127
*/
6.通过指针函数遍历数组:
$array = ['c',null,null => false,0,''=>'naxx','22332',222];
print_r($array);
//不对的,有的值正好是false,0,null
while (current($array)) {
echo '当前指针位置的键名:',key($array),'<br/>';
echo '当前指针位置的键值:',current($array),'<br/>';
next($array);
}
/*
Array
(
[0] => c
[1] =>
[] => naxx
[2] => 0
[3] => 22332
[4] => 222
)
当前指针位置的键名:0
当前指针位置的键值:c
*/
reset($array);
echo '<hr/>';
while (!is_null(key($array))) {
echo '当前指针位置的键名:',key($array),'<br/>';
echo '当前指针位置的键值:',current($array),'<br/>';
echo "<br/>";
next($array);
}
/*
当前指针位置的键名:0
当前指针位置的键值:c
当前指针位置的键名:1
当前指针位置的键值:
当前指针位置的键名:
当前指针位置的键值:naxx
当前指针位置的键名:2
当前指针位置的键值:0
当前指针位置的键名:3
当前指针位置的键值:22332
当前指针位置的键名:4
当前指针位置的键值:222
*/
7.end() 取得文件扩展名
$filename = '1229293.2xxx.php';
$arrs = explode('.', $filename);//按'.'分割成数组
print_r($arrs);
$extesion = end($arrs);//通过指针获取数组末尾的元素
echo $extesion; //php
数组运算符
1.合并数组 +,如果数组键名(比如下标相同的数组元素)相同,则只会使用左边的数组的键值,而不是覆盖!
$arr1 = ['a','b','c'];
$arr2 = ['a',11,true,'d'];
$newArr = $arr1 + $arr2;
print_r($newArr);
2.比较数组的键名和键值是否相同 == 相同返回true,否则返回false !=相反
$arr1 = ['id'=>1,'name'=>'zhangsan','age'=>23];
$arr2 = ['id'=>1,'age'=>23,'name'=>'zhangsan'];
$arr3 = ['id'=>2,'age'=>19,'name'=>'lisi'];
$arr4 = ['id'=>1,'name'=>'zhangsan','age'=>23];
var_dump($arr1 == $arr2); //true
var_dump($arr1 == $arr3); //false
var_dump($arr1 == $arr4); //true
var_dump($arr1 != $arr3); //true
var_dump($arr1 != $arr4); //false
3.比较数组的键名和键值是否相同,同时顺序也要相同,即全等于 === 相同返回true,否则返回false !== 相反
var_dump($arr1 === $arr2); //false
var_dump($arr1 === $arr4); //true
var_dump($arr1 !== $arr2); //true
var_dump($arr1 !== $arr4); //false
each()和list()
1.each()返回数组中当前的键/值对,并将数组指针向前移动一步,返回的是一个包含四个元素的数组,键名为0,1,key,value,0和key对应的是当前指针对应的键名,1和value对应的是当前指针对应的键值.如果当前指针不在数组范围中,返回false
$foo = array('name'=>"bob", "fred",233);
$bar = each($foo);
print_r($bar);
echo '当前指针位置的键名:',key($foo),'<br/>';
echo '当前指针位置的键值:',current($foo),'<br/>';
$bar = each($foo);
echo '当前指针位置的键名:',key($foo),'<br/>';
echo '当前指针位置的键值:',current($foo),'<br/>';
$bar = each($foo);
echo '当前指针位置的键名:',key($foo),'<br/>';
echo '当前指针位置的键值:',current($foo),'<br/>';
var_dump(each($foo));
/*
Array
(
[1] => bob
[value] => bob
[0] => name
[key] => name
)
当前指针位置的键名:0
当前指针位置的键值:fred
当前指针位置的键名:1
当前指针位置的键值:233
当前指针位置的键名:
当前指针位置的键值:
bool(false)
*/
2.list()把数组中的值赋给一组变量,感觉类似于ES6的解构赋值
$info = array('coffee', 'brown', 'caffeine');
// 列出所有变量
list($drink, $color, $power) = $info;
echo "$drink is $color and $power makes it special.\n";
// 列出他们的其中一个
list($drink, , $power) = $info;
echo "$drink has $power.\n";
// 或者让我们跳到仅第三个
list(,,$power) = $info;
echo "I need $power!\n";
// list() 不能对字符串起作用
list($bar) = "abcde";
var_dump($bar); // NULL
/*
coffee is brown and caffeine makes it special.
coffee has caffeine.
I need caffeine!
NULL
*/
2.1 list() 嵌套元素,也是可以获取值的
list($a,list($b,$c)) = array('apple',['hello',23]);
var_dump($a,$b,$c);
/*
string(5) "apple"
string(5) "hello"
int(23)
*/
2.2 list() 使用数组索引 php5和php7的顺序不一样,php7从左到右,php5相反
list($arr[0],list($arr[1],$arr[2])) = array('apple',['hello',23]);
var_dump($arr);
2.3 list() []空数组
list($a) = array();
var_dump($a); //null
list(,,$a) = array();
var_dump($a);//null
2.4 list()循环[] 关联数组不可用,使用索引数组(下标连续且从0开始),内部是按下标一一进行赋值
$arr = [
['name'=>"adson",'age'=>22,'sex'=>true],
['name'=>"adson1",'age'=>23,'sex'=>true],
['name'=>"adson3",'age'=>24,'sex'=>true],
['name'=>"adson4",'age'=>25,'sex'=>true]
];
foreach ($arr as list($name,$age,$sex)) {
echo $name,'---',$age,'---',$sex,'<br/>';
}
/*输出:
------
------
------
------
*/
$arrs = [
['aleen',23,true],
['alex',24,false],
['lisa',21,true]
];
foreach ($arrs as list($name,$age,$sex)) {
echo $name,'---',$age,'---',$sex,'<br/>';
}
/*
aleen---23---1
alex---24---
lisa---21---1
*/
2.5 each() list()遍历数组
$fruit = array(
'a' => 'apple',
'b' => 'banana',
'c' => 'cranberry'
);
reset($fruit);
while (list($key, $val) = each($fruit)) {
echo "$key => $val\n";
}
/*
a => apple
b => banana
c => cranberry
*/
2.6 caution:将一个数组赋值给另一个数组时会重置原来的数组指针,导致死循环
// reset($fruit);
// while (list($key, $val) = each($fruit)) {
// echo "$key => $val\n";
// //重新赋值
// $fruit = ['x'];
// }