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 数组可以同时含有 integerstring 类型的键名,因为 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 - 使用用户自定义的比较函数对数组中的值进行排序