數組是 PHP 中最核心、最靈活的數據結構。掌握數組操作是寫出高效、優雅 PHP 代碼的關鍵。本文系統梳理數組的創建、遍歷、增刪改查、合併拆分、排序過濾等全方位操作,並提供性能優化與避坑指南。
<?php
// 1. 索引數組 - 數字鍵(自動/手動)
$indexed = ['Apple', 'Banana', 'Cherry'];
$indexed = [0 => 'Apple', 5 => 'Banana', 10 => 'Cherry']; // 稀疏數組
// 2. 關聯數組 - 字符串鍵
$assoc = [
'name' => '張三',
'age' => 25,
'city' => '北京'
];
// 3. 多維數組 - 數組嵌套
$multi = [
'users' => [
['id' => 1, 'name' => 'Alice'],
['id' => 2, 'name' => 'Bob'],
],
'config' => [
'db' => ['host' => 'localhost', 'port' => 3306],
'redis' => ['host' => '127.0.0.1', 'port' => 6379],
]
];
// 判斷類型
function arrayType(array $arr): string {
if ($arr === []) return 'empty';
$keys = array_keys($arr);
$allInt = array_reduce($keys, fn($c, $k) => $c && is_int($k), true);
$allStr = array_reduce($keys, fn($c, $k) => $c && is_string($k), true);
return $allInt ? 'indexed' : ($allStr ? 'associative' : 'mixed');
}
?>
<?php
// 短語法
$arr = [1, 2, 3];
$assoc = ['key' => 'value'];
// 範圍創建
$range = range(1, 100); // 1..100
$letters = range('a', 'z'); // a..z
$step = range(0, 100, 10); // 0,10,20..100
// 填充創建
$filled = array_fill(0, 10, 'default'); // 10個默認值
$filledKeys = array_fill_keys(['a','b','c'], 0); // 指定鍵填充
?>
<?php
$data = ['a' => 1, 'b' => 2, 'c' => 3];
// 1. foreach (值) - 最常用,語法清晰
foreach ($data as $value) { /* ... */ }
// 2. foreach (鍵 => 值) - 需要鍵時
foreach ($data as $key => $value) { /* ... */ }
// 3. for 循環 - 索引數組、需控制步長
for ($i = 0, $len = count($data); $i < $len; $i++) { /* ... */ }
// 4. while + each/list - 老式,已棄用
while (list($key, $value) = each($data)) { /* ... */ }
// 5. ArrayIterator - 面向對象、可嵌套遍歷
$iterator = new ArrayIterator($data);
foreach ($iterator as $key => $value) { /* ... */ }
?>
| 方式 | 耗時(秒) | 內存 | 推薦場景 |
|---|---|---|---|
| foreach (值) | 0.08 | 低 | 通用首選 |
| foreach (鍵=>值) | 0.09 | 低 | 需鍵操作 |
| for 循環 | 0.12 | 低 | 索引數組、逆序、步長控制 |
| array_walk | 0.25 | 中 | 需引用修改原數組 |
| ArrayIterator | 0.35 | 高 | 對象風格、多重迭代器 |
<?php $arr = ['a', 'b']; // 尾部添加(推薦) $arr[] = 'c'; // 最快 array_push($arr, 'd', 'e'); // 批量添加,返回新長度 // 頭部添加 array_unshift($arr, 'first'); // 返回新長度,重新索引 // 指定位置插入 array_splice($arr, 2, 0, 'inserted'); // 索引2處插入,不刪除 ?>
<?php $arr = ['a', 'b', 'c', 'd']; // 尾部刪除 $last = array_pop($arr); // 返回被刪值 // 頭部刪除 $first = array_shift($arr); // 返回被刪值,重新索引 // 指定鍵刪除 unset($arr['key']); // 不重新索引,保留鍵名 array_splice($arr, 1, 2); // 索引1起刪2個,重新索引 // 按值刪除 $arr = array_diff($arr, ['b']); // 保留鍵名 $arr = array_values(array_diff($arr, ['b'])); // 重新索引 ?>
<?php
$arr = ['a' => 1, 'b' => 2, 'c' => 3];
// 修改
$arr['b'] = 20;
$arr['d'] = 4; // 新增
// 存在性檢查
isset($arr['b']); // true,鍵存在且非 null
array_key_exists('b', $arr); // true,鍵存在(含 null 值)
in_array(2, $arr); // 值存在,O(n)
array_search(2, $arr); // 返回鍵 'b',嚴格模式第3參數 true
// 獲取鍵/值
array_keys($arr); // ['a','b','c']
array_values($arr); // [1,20,3] 重新索引
array_flip($arr); // 鍵值互換 [1=>'a', 20=>'b', 3=>'c']
?>
<?php $a = ['a' => 1, 'b' => 2]; $b = ['b' => 3, 'c' => 4]; // array_merge: 字符串鍵後者覆蓋,數字鍵重新索引追加 array_merge($a, $b); // ['a'=>1, 'b'=>3, 'c'=>4, 0=>?] // + 運算符: 鍵衝突保留第一個 $a + $b; // ['a'=>1, 'b'=>2, 'c'=>4] // array_merge_recursive: 衝突鍵合併為數組 array_merge_recursive($a, $b); // ['a'=>1, 'b'=>[2,3], 'c'=>4] // array_combine: 兩數組組成鍵值對 array_combine(['x','y'], [10,20]); // ['x'=>10, 'y'=>20] ?>
<?php $a = [1, 2, 3, 4]; $b = [3, 4, 5, 6]; array_intersect($a, $b); // [2=>3, 3=>4] 保留鍵 array_diff($a, $b); // [0=>1, 1=>2] 在a不在b array_diff_assoc($a, $b); // 鍵值都比較 // 關聯數組專用 $a = ['x'=>1, 'y'=>2]; $b = ['x'=>1, 'z'=>3]; array_intersect_assoc($a, $b); // ['x'=>1] array_diff_assoc($a, $b); // ['y'=>2] ?>
<?php $arr = range(1, 10); // array_slice: 切片(不修改原數組) array_slice($arr, 2, 3); // [3,4,5] 從索引2取3個 array_slice($arr, -3); // [8,9,10] 最後3個 array_slice($arr, 2, -1); // [3,4,5,6,7,8,9] 索引2到倒數第2 // array_chunk: 分塊 array_chunk($arr, 3); // [[1,2,3],[4,5,6],[7,8,9],[10]] array_chunk($arr, 3, true); // 保留鍵 ?>
<?php $arr = range(1, 10); shuffle($arr); // 原地打亂 array_rand($arr, 3); // 返回3個隨機鍵 // PHP 7.1+ 使用 Mersenne Twister,質量更好 ?>
<?php $nums = [10, 20, 30, 'abc', 40]; array_sum($nums); // 100 (忽略非數字) array_product($nums); // 2400000 count($nums); // 5 count($nums, COUNT_RECURSIVE); // 遞歸計數 ?>
<?php
$users = [
['name' => 'Alice', 'age' => 25],
['name' => 'Bob', 'age' => 30],
['name' => 'Charlie', 'age' => 35],
];
// array_map: 映射轉換
$names = array_map(fn($u) => $u['name'], $users);
// ['Alice', 'Bob', 'Charlie']
// array_filter: 過濾
$adults = array_filter($users, fn($u) => $u['age'] >= 30);
// 保留鍵:[1=>..., 2=>...]
// array_reduce: 歸約
$totalAge = array_reduce($users, fn($carry, $u) => $carry + $u['age'], 0);
// 90
// array_walk: 遍歷修改(引用)
array_walk($users, fn(&$u) => $u['age']++);
// 原數組年齡+1
?>
| 函數 | 排序依據 | 鍵名保留 | 返回值 |
|---|---|---|---|
| sort | 值升序 | 否(重新索引) | bool |
| rsort | 值降序 | 否 | bool |
| asort | 值升序 | 是 | bool |
| arsort | 值降序 | 是 | bool |
| ksort | 鍵升序 | 是 | bool |
| krsort | 鍵降序 | 是 | bool |
| usort | 自定義值比較 | 否 | bool |
| uasort | 自定義值比較 | 是 | bool |
| uksort | 自定義鍵比較 | 是 | bool |
| natsort | 自然排序 | 是 | bool |
<?php
// 多維數組排序
usort($users, fn($a, $b) => $a['age'] <=> $b['age']);
// 多字段排序:先按年齡升序,同齡按名字降序
usort($users, fn($a, $b) =>
[$a['age'], strtolower($b['name'])] <=>
[$b['age'], strtolower($a['name'])]
);
// array_multisort: 多數組/多鍵同步排序
$ages = array_column($users, 'age');
$names = array_column($users, 'name');
array_multisort($ages, SORT_ASC, $names, SORT_DESC, $users);
?>
<?php
// 1. 引用殘留
$arr = [1,2,3];
foreach ($arr as &$v) { $v *= 2; }
unset($v); // 必須解除引用!
foreach ($arr as $v) { } // 否則最後一個元素會被意外修改
// 2. 數字鍵自動轉換
$arr = ['0' => 'a', '1' => 'b']; // 字符串鍵
$arr[0] = 'c'; // 實際覆蓋 '0' => 'a'
var_dump($arr); // [0=>'c', 1=>'b']
// 3. 空數組行為
array_merge([]); // []
array_merge([], [1]); // [0=>1]
[] + [1]; // [0=>1]
// 4. count() 陷阱
count(null); // 1 (PHP 7.2+ 警告)
count(false); // 1
count([1,2], COUNT_RECURSIVE); // 遞歸計數
?>
<?php
// 1. 類型聲明(PHP 7.0+)
function processUsers(array $users): array {
return array_map(fn(array $u): array => [
'id' => $u['id'],
'name' => trim($u['name']),
], $users);
}
// 2. 解構賦值(PHP 7.1+)
[$first, $second] = $arr;
['id' => $id, 'name' => $name] = $user;
// 3. 展開運算符(PHP 7.4+)
$merged = [...$arr1, ...$arr2];
$withDefaults = ['a' => 1, ...$userInput];
// 4. 箭頭函數(PHP 7.4+)
$doubled = array_map(fn($n) => $n * 2, $numbers);
// 5. nullsafe 操作符(PHP 8.0+)
$city = $user['address']['city'] ?? '未知';
?>
PHP 數組功能強大但易誤用。核心原則:明確數組類型(索引/關聯)、選擇正確遍歷方式、善用內置函數避免手寫循環、注意引用殘留與鍵名轉換、利用現代語法提升可讀性。對於複雜數據處理,考慮引入 Collection 庫(如 Laravel Collections、illuminate/support)獲得鏈式調用與不可變操作體驗。