1. 介绍
PHP 的数组实际上是一个有序映射。映射是一种把 values 关联到 keys 的类型。此类型在很多方面做了优化,因此可以把它当成真正的数组,或列表(向量),hash 表(映射的一种实现),字典,集合,栈,队列或者更多可能。由于数组元素的值也可以是另一个数组,树形结构和多维数组也是允许的。
对于每种结构至少会提供一个例子,要了解更多信息,建议参考相关的著作。
2. 语法
2.1 定义数组
可以用 array()
语言结构来新建一个数组。它接受任意数量用逗号分隔的键值对「key => value」。
$array = array(
"foo" => "bar",
"bar" => "foo",
);
从 5.4 开始,也可以使用短数组定义语法,用 []
代替 array()
。
$array = [
"foo" => "bar",
"bar" => "foo",
];
key
可以是 integer
或者 string
。value 可以是任意类型。
此外 key
会有如下的强制转换:
- 包含有合法整数值的字符串会被转换为整型。例如键名「"8"」实际会被存储为 8。但是「"08"」则不会强制转换,因为这不是一个合法的十进制数。
- 浮点数也会被转换为整型,意味着小数部分会被舍去。例如键名 8.7 实际会被存储为 8。
- 布尔值也会被转换为整型,即键名
true
实际会被存储为 1,而键名false
会被存储为 0。 NULL
会被转换为空字符串,即键名null
实际会被存储为「''」。- 数组和对象不能被用作键名,这会导致警告:illegal offset type。
如果在数组定义中多个单元都使用了同一键名,则只会使用最后一个,之前的都会被覆盖。
/*
* 类型强制转换与覆盖
*/
$array = array(
1 => "a",
"1" => "b",
1.5 => "c",
true => "d"
);
var_dump($array);
/* 结果
array (size=1)
1 => string 'd' (length=1)
*/
上例中所有的键名都被强制转换为 1,每一个新单元都会覆盖前一个的值,最后只剩下一个「d」。
PHP 数组可以同时含有 integer
和 string
类型的键名,因为 PHP 实际并不区分索引数组和关联数组。
如果给出的值没有指定键名,则取当前最大的整数索引值,而新的键名将是该值加 1。如果指定的键名已经有值,则该值会被覆盖。
/*
* 混合 integer 和 string 键名
*/
$array = array(
"foo" => "bar",
"bar" => "foo",
100 => -100,
-100 => 100,
);
var_dump($array);
/* 输出
array (size=4)
'foo' => string 'bar' (length=3)
'bar' => string 'foo' (length=3)
100 => int -100
-100 => int 100
*/
key
为可选项。如果未指定,PHP 将自动使用之前用过的最大的 integer
键名加上 1 作为新的键名。
/*
* 没有键名的索引数组
*/
$array = array("foo", "bar", "hello", "world");
var_dump($array);
/* 输出
array (size=4)
0 => string 'foo' (length=3)
1 => string 'bar' (length=3)
2 => string 'hello' (length=5)
3 => string 'world' (length=5)
*/
还可以只对某些单元指定键名而对其它的空置:
/*
* 仅对部分单元指定键名
*/
$array = array(
"a",
"b",
6 => "c",
"d",
);
var_dump($array);
/* 输出
array (size=4)
0 => string 'a' (length=1)
1 => string 'b' (length=1)
6 => string 'c' (length=1)
7 => string 'd' (length=1)
*/
可以看到最后一个值「d」被自动赋予了键名 7。这是由于之前最大的整数键名是 6。
2.2 访问数组
数组单元可以用方括号语法 array[key]
来访问。
/*
* 访问数组元素
*/
$array = [
"foo" => "bar",
42 => 24,
"multi" => [
"dimensional" => [
"array" => "foo"
]
]
];
var_dump($array["foo"]);
var_dump($array[42]);
var_dump($array["multi"]["dimensional"]["array"]);
/* 输出
string 'bar' (length=3)
int 24
string 'foo' (length=3)
*/
方括号和花括号可以互换使用来访问数组单元(例如
$array[42]
和$array{42}
在上例中效果相同)。
自 PHP 5.4 起可以直接对函数或方法返回的结果进行数组解引用,在此之前只能通过一个临时变量。
自 PHP 5.5 起可以直接对一个数组原型进行数组解引用。
/*
* 数组解引用
*/
function getArray() {
return array(1, 2, 3);
}
// PHP 5.4
$secondElement = getArray()[1];
// 之前版本
$tmp = getArray();
$secondElement = $tmp[1];
// 或者这样
list(, $secondElement) = getArray();
试图访问一个未定义的数组键名与访问任何未定义变量一样,会导致 E_NOTICE 级别错误,其结果为
NULL
。
2.3 修改数组
可以用方括号语法来显示的修改一个已有数组。
这是通过在方括号内指定键名来给数组赋值实现的。也可以省略键名,在这种情况下给变量名加上一对空的方括号([])。
$arr[key] = value;
$arr[] = value;
如果 $arr
还不存在,将会新建一个,这也是另外一种新建数组的方法。不过并不推荐这样做,因为如果 $arr
已经包含有值,则此值会保留,而 []
实际上代表着字符串访问运算符。初始化变量的最好方式是直接给其赋值。
要修改某个值,通过其键名给该单元赋一个新值。要删除某键值对,对其使用 unset()
函数。
$arr = [
5 => 1,
12 => 2
];
$arr[] = 56; // 等同于 $arr[13] = 56;
$arr["x"] = 42; // 添加一个键为 x 的新元素
unset($arr[5]); // 从数组中删除元素
unset($arr); // 删除整个数组
如上所述,如果给出方括号但没有指定键名,则取当前最大整数索引值,新的键名将是该值加 1(但是最小为 0)。如果当前还没有整数索引,则键名将为 0。
注意这里所使用的最大整数键名不一定当前就在数组中。它只要在上次数组重新生成索引后曾经存在过就可以了。
// 创建一个简单的数组
$array = [1, 2, 3, 4, 5];
print_r($array);
/* 输出
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
)
*/
// 现在删除其中的所有元素,但保持数组本身不变
foreach ($array as $i => $value) {
unset($array[$i]);
}
print_r($array);
/* 输出
Array ( )
*/
// 添加一个单元(注意新的键名是 5,而不是你可能认为的 0)
$array[] = 6;
print_r($array);
/* 输出
Array
(
[5] => 6
)
*/
// 重新索引
$array = array_values($array);
$array[] = 7;
print_r($array);
/* 输出
Array
(
[0] => 6
[1] => 7
)
*/
3. 实用函数
有很多操作数组的函数,参见 数组函数。
array_change_key_case
- 将数组中的所有键名修改为全大写或者小写
array_chunk
- 将一个组数分割成多个
array_column
- 返回数组中指定的一列
array_combine
- 创建一个数组,用一个数组的值作为其键名,另一个数组的值作为其值
array_count_values
- 统计数组中所有的值
array_diff_assoc
- 带索引检查计算数组的差集
array_diff_key
- 使用键名比较计算数组的差集
array_diff_uassoc
- 用用户提供的回调函数做索引检查来计算数组的差集
array_diff_ukey
- 用回调函数对键名比较计算数组的差集
array_diff
- 计算数组的差集
array_fill_keys
- 使用指定的键和值填充数组
array_fill
- 用给定的值填充数组
array_filter
- 用回调函数过滤数组中的单元
array_flip
- 交换数组中的键和值
array_intersect_assoc
- 带索引检查计算数组的交集
array_intersect_key
- 使用键名比较计算数组的交集
array_intersect_uassoc
- 带索引检查计算数组的交集,用回调函数比较索引
array_intersect_ukey
- 用回调函数比较键名来计算数组的交集
array_intersect
- 计算数组的交集
array_key_exists
- 检查数组里是否有指定的键名或索引
array_key_first
- 获取数组第一个键名或索引
array_key_last
- 获取数组最后一个键名或索引
array_keys
- 返回数组中部分或所有的键名
array_map
- 为数组的每个元素应用回调函数
array_merge_recursive
- 递归的合并一个或多个数组
array_merge
- 合并一个或多个数组
array_multisort
- 对多个数组或多维数组进行排序
array_pad
- 以指定长度将一个值填充进数组
array_pop
- 弹出数组最后一个单元(出栈)
array_product
- 计算数组中所有值的乘积
array_push
- 将一个或多个单元压入数组的末尾(入栈)
array_rand
- 从数组中随机取出一个或多个单元
array_reduce
- 用回调函数迭代的将数组简化为单一的值
array_replace_resursive
- 使用传递的数组递归替换第一个数组的元素
array_replace
- 使用传递的数组替换第一个数组的元素
array_reverse
- 返回单元顺序相反的数组
array_search
- 在数组中搜索给定的值,如果成功则返回首个相应的键名
array_shift
- 将数组开头的单元移出数组
array_slice
- 对数组中取出一段
array_splice
- 去掉数组中的某一部分并用其它值代替
array_sum
- 对数组中所有值求和
array_udiff_assoc
- 带索引检查计算数组的差集,用回调函数比较数据
array_udiff_uassoc
- 带索引检查计算数组的差集,用回调函数比较数据和索引
array_udiff
- 用回调函数比较数据来计算数组的差集
array_uintersect_assoc
- 带索引检查计算数组的交集,用回调函数比较数据
array_uintersect_uassoc
- 带索引检查计算数组的交集,用单独的回调函数比较数据和索引
array_uintersect
- 计算数组的交集,用回调函数比较数据
array_unique
- 移除数组中重复的值
array_unshift
- 在数组开头插入一个或多个单元
array_values
- 返回数组中所有的值
array_walk_recursive
- 对数组中的每个成员递归的应用用户函数
array_walk
- 使用用户自定义函数对数组中的每个元素做回调处理
array
- 新建一个数组
arsort
- 对数组进行逆向排序并保持索引关系
asort
- 对数组进行排序兵保持索引关系
compact
- 建立一个数组,包括变量名和它们的值
count
- 计算数组中的单元数目,或对象的属性个数
current
- 返回数组中的当前单元
end
- 将数组的内部指针指向最后一个单元
extract
- 从数组中将变量导入到当前的符号表
in_array
- 检查数组中是否存在某个值
key
- 从关联数组中取得键名
krsort
- 对数组按照键名逆向排序
ksort
- 对数组按照键名排序
list
- 把数组的值赋给一组变量
natcasesort
- 用「自然排序」算法对数组进行不区分大小写字母的排序
natsort
- 用「自然排序」算法对数组排序
next
- 将数组的内部指针向后移动一位
prev
- 将数组的内部指针倒回一位
range
- 根据范围创建数组,包含指定的元素
reset
- 将数组的内部指针指向第一个单元
rsort
- 对数组逆向排序
shuffle
- 打乱数组
sort
- 对数组排序
uasort
- 使用用户自定义的比较函数对数组中的值进行排序并保持索引关联
uksort
- 使用用户自定义的比较函数对数组中的键名进行排序
usort
- 使用用户自定义的比较函数对数组中的值进行排序