多维数组
多维数组是指数组中包含其他数组作为其元素的数据结构。在PHP中,你可以创建二维、三维甚至更高维度的数组来组织和存储复杂的数据。多维数组在处理表格数据、配置文件、嵌套数据结构等方面非常有用。
什么是多维数组?
多维数组(Multidimensional Array)是包含一个或多个数组的数组。最常见的多维数组是二维数组,可以想象成表格或矩阵的形式。
// 二维数组示例 - 表格数据
$students = [
["张三", 20, "计算机科学"],
["李四", 21, "软件工程"],
["王五", 19, "信息安全"]
];
// 三维数组示例 - 多个班级的学生
$school = [
"class1" => [
["张三", 20, "计算机科学"],
["李四", 21, "软件工程"]
],
"class2" => [
["王五", 19, "信息安全"],
["赵六", 20, "人工智能"]
]
];
创建多维数组
1. 直接创建
// 二维数组 - 产品信息表
$products = [
["iPhone 15", "Apple", 5999, "手机"],
["MacBook Pro", "Apple", 14999, "笔记本"],
["Galaxy S24", "Samsung", 4999, "手机"],
["ThinkPad X1", "Lenovo", 12999, "笔记本"]
];
// 三维数组 - 销售数据
$salesData = [
"2023" => [
"Q1" => [100000, 120000, 110000],
"Q2" => [130000, 140000, 125000],
"Q3" => [135000, 145000, 130000],
"Q4" => [150000, 160000, 140000]
],
"2024" => [
"Q1" => [155000, 165000, 150000],
"Q2" => [160000, 170000, 155000],
"Q3" => [165000, 175000, 160000],
"Q4" => [170000, 180000, 165000]
]
];
2. 逐步构建
// 创建空的二维数组
$matrix = [];
// 逐行添加数据
for ($i = 0; $i < 3; $i++) {
$row = [];
for ($j = 0; $j < 3; $j++) {
$row[] = $i * 3 + $j + 1;
}
$matrix[] = $row;
}
// 结果:[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
// 动态创建用户数据
$users = [];
$userData = [
["张三", "zhangsan@example.com", "北京"],
["李四", "lisi@example.com", "上海"],
["王五", "wangwu@example.com", "广州"]
];
foreach ($userData as $data) {
$users[] = [
"name" => $data[0],
"email" => $data[1],
"city" => $data[2],
"profile" => [
"age" => rand(20, 30),
"status" => "active",
"level" => "standard"
]
];
}
3. 使用函数创建
// 使用array_fill创建二维数组
$grid = array_fill(0, 3, array_fill(0, 4, 0));
// 结果:3x4的零矩阵
// 使用range创建
$multiplicationTable = [];
for ($i = 1; $i <= 9; $i++) {
$multiplicationTable[] = range($i, $i * 9, $i);
}
// 创建更复杂的三维数组
$categories = [
"electronics" => ["phones", "laptops", "tablets"],
"clothing" => ["shirts", "pants", "shoes"],
"books" => ["fiction", "non-fiction", "textbooks"]
];
$inventory = [];
foreach ($categories as $category => $items) {
$inventory[$category] = [];
foreach ($items as $item) {
$inventory[$category][$item] = [
"stock" => rand(10, 100),
"price" => rand(100, 1000),
"supplier" => "供应商" . rand(1, 5)
];
}
}
访问多维数组
1. 基本访问方式
$students = [
["张三", 20, "计算机科学", [85, 92, 78]],
["李四", 21, "软件工程", [90, 88, 95]],
["王五", 19, "信息安全", [82, 79, 88]]
];
// 访问二维数组元素
echo $students[0][0]; // 输出:张三
echo $students[1][2]; // 输出:软件工程
// 访问三维数组元素
echo $students[0][3][0]; // 输出:85(张三的第一个成绩)
// 修改元素
$students[0][1] = 22; // 张三年龄改为22
$students[1][3][1] = 91; // 李四第二个成绩改为91
2. 使用键名的访问
$employees = [
"dept1" => [
"manager" => ["name" => "张经理", "salary" => 15000],
"staff" => [
["name" => "李四", "salary" => 8000],
["name" => "王五", "salary" => 7500]
]
],
"dept2" => [
"manager" => ["name" => "赵经理", "salary" => 14000],
"staff" => [
["name" => "钱六", "salary" => 8500],
["name" => "孙七", "salary" => 7200]
]
]
];
// 访问嵌套数据
echo $employees["dept1"]["manager"]["name"]; // 输出:张经理
echo $employees["dept1"]["staff"][0]["salary"]; // 输出:8000
echo $employees["dept2"]["staff"][1]["name"]; // 输出:孙七
// 安全访问(检查键是否存在)
$dept3Manager = $employees["dept3"]["manager"]["name"] ?? "未知部门";
echo $dept3Manager; // 输出:未知部门
3. 动态访问
$config = [
"database" => [
"connections" => [
"mysql" => [
"host" => "localhost",
"port" => 3306,
"database" => "myapp"
],
"postgres" => [
"host" => "localhost",
"port" => 5432,
"database" => "myapp_pg"
]
]
]
];
// 使用变量访问
$connectionType = "mysql";
$host = $config["database"]["connections"][$connectionType]["host"];
echo $host; // 输出:localhost
// 函数式访问
function getConfigValue($config, $path, $default = null) {
$keys = explode(".", $path);
$current = $config;
foreach ($keys as $key) {
if (!is_array($current) || !array_key_exists($key, $current)) {
return $default;
}
$current = $current[$key];
}
return $current;
}
$dbPort = getConfigValue($config, "database.connections.postgres.port", 3306);
echo $dbPort; // 输出:5432
遍历多维数组
1. 嵌套foreach循环
$matrix = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]
];
// 遍历二维数组
echo "=== 矩阵内容 ===\n";
foreach ($matrix as $rowIndex => $row) {
foreach ($row as $colIndex => $value) {
echo "[{$rowIndex}][{$colIndex}] = {$value}\t";
}
echo "\n";
}
// 计算每行的和
foreach ($matrix as $rowIndex => $row) {
$rowSum = array_sum($row);
echo "第 {$rowIndex} 行的和:{$rowSum}\n";
}
2. 遍历复杂的多维数组
$products = [
"electronics" => [
"phones" => [
["iPhone 15", 5999, 50],
["Samsung S24", 4999, 30]
],
"laptops" => [
["MacBook Pro", 14999, 20],
["ThinkPad X1", 12999, 15]
]
],
"clothing" => [
"shirts" => [
["T-Shirt", 99, 100],
["Dress Shirt", 199, 50]
]
]
];
// 遍历并格式化输出
foreach ($products as $category => $categories) {
echo "分类:{$category}\n";
foreach ($categories as $subCategory => $items) {
echo " 子分类:{$subCategory}\n";
foreach ($items as $item) {
list($name, $price, $stock) = $item;
echo " - {$name}:¥{$price} (库存:{$stock})\n";
}
}
echo "\n";
}
3. 使用递归遍历
$data = [
"level1" => [
"level2" => [
"level3" => "深度值",
"level3_b" => ["深度数组", "嵌套值"]
],
"level2_b" => "中级值"
],
"level1_b" => "表层值"
];
// 递归遍历函数
function traverseArray($array, $depth = 0) {
$indent = str_repeat(" ", $depth);
foreach ($array as $key => $value) {
if (is_array($value)) {
echo "{$indent}{$key}:\n";
traverseArray($value, $depth + 1);
} else {
echo "{$indent}{$key}: {$value}\n";
}
}
}
// 扁平化数组函数
function flattenArray($array, $prefix = "") {
$result = [];
foreach ($array as $key => $value) {
$newKey = $prefix ? "{$prefix}.{$key}" : $key;
if (is_array($value)) {
$result = array_merge($result, flattenArray($value, $newKey));
} else {
$result[$newKey] = $value;
}
}
return $result;
}
echo "=== 递归遍历结果 ===\n";
traverseArray($data);
echo "\n=== 扁平化结果 ===\n";
$flattened = flattenArray($data);
print_r($flattened);
常用操作
1. 数组转换
// 二维数组转一维数组
$students = [
["张三", 20, "计算机科学"],
["李四", 21, "软件工程"],
["王五", 19, "信息安全"]
];
// 提取所有姓名
$names = array_column($students, 0);
// 结果:["张三", "李四", "王五"]
// 使用关联数组
$users = [
["id" => 1, "name" => "张三", "email" => "zhangsan@example.com"],
["id" => 2, "name" => "李四", "email" => "lisi@example.com"],
["id" => 3, "name" => "王五", "email" => "wangwu@example.com"]
];
// 提取name列,以id为键
$userNames = array_column($users, "name", "id");
// 结果:[1 => "张三", 2 => "李四", 3 => "王五"]
// 转置矩阵
function transpose($matrix) {
return array_map(null, ...$matrix);
}
$matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
];
$transposed = transpose($matrix);
// 结果:[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
2. 搜索和过滤
$products = [
["iPhone 15", "Apple", 5999, "electronics"],
["MacBook Pro", "Apple", 14999, "electronics"],
["T-Shirt", "H&M", 99, "clothing"],
["Jeans", "Levi's", 399, "clothing"]
];
// 搜索特定商品
function searchProduct($products, $searchTerm) {
$results = [];
foreach ($products as $product) {
if (stripos($product[0], $searchTerm) !== false) {
$results[] = $product;
}
}
return $results;
}
$appleProducts = searchProduct($products, "Apple");
print_r($appleProducts);
// 按分类过滤
function filterByCategory($products, $category) {
return array_filter($products, function($product) use ($category) {
return $product[3] === $category;
});
}
$electronics = array_values(filterByCategory($products, "electronics"));
print_r($electronics);
// 按价格范围过滤
function filterByPriceRange($products, $minPrice, $maxPrice) {
return array_filter($products, function($product) use ($minPrice, $maxPrice) {
return $product[2] >= $minPrice && $product[2] <= $maxPrice;
});
}
$midRange = array_values(filterByPriceRange($products, 100, 1000));
print_r($midRange);
3. 排序和多维排序
$employees = [
["张三", "技术部", 8000, 25],
["李四", "销售部", 6000, 28],
["王五", "技术部", 9000, 30],
["赵六", "市场部", 7000, 26]
];
// 按工资排序(降序)
usort($employees, function($a, $b) {
return $b[2] - $a[2]; // 按第3个元素(工资)降序
});
echo "按工资排序:\n";
foreach ($employees as $emp) {
echo "{$emp[0]}:{$emp[2]}元\n";
}
// 复杂排序:先按部门,再按工资
usort($employees, function($a, $b) {
if ($a[1] === $b[1]) {
return $b[2] - $a[2]; // 同部门按工资降序
}
return strcmp($a[1], $b[1]); // 按部门名称升序
});
echo "\n按部门和工资排序:\n";
foreach ($employees as $emp) {
echo "{$emp[1]} - {$emp[0]}:{$emp[2]}元\n";
}
// 使用array_multisort排序
$names = array_column($employees, 0);
$salaries = array_column($employees, 2);
// 按工资降序,工资相同按姓名升序
array_multisort($salaries, SORT_DESC, $names, SORT_ASC, $employees);
实际应用示例
1. 学生成绩管理系统
<?php
class GradeManager {
private $students = [];
private $subjects = [];
public function __construct() {
$this->subjects = ["语文", "数学", "英语", "物理", "化学"];
}
// 添加学生
public function addStudent($name, $class) {
$studentId = count($this->students) + 1;
$this->students[$studentId] = [
"id" => $studentId,
"name" => $name,
"class" => $class,
"grades" => array_fill(0, count($this->subjects), 0),
"exams" => []
];
return $studentId;
}
// 设置成绩
public function setGrade($studentId, $subjectIndex, $grade) {
if (isset($this->students[$studentId])) {
$this->students[$studentId]["grades"][$subjectIndex] = $grade;
return true;
}
return false;
}
// 添加考试成绩
public function addExamResult($studentId, $examName, $grades) {
if (isset($this->students[$studentId])) {
$this->students[$studentId]["exams"][] = [
"exam_name" => $examName,
"date" => date("Y-m-d"),
"grades" => $grades,
"total" => array_sum($grades),
"average" => array_sum($grades) / count($grades)
];
return true;
}
return false;
}
// 获取学生总分
public function getTotalScore($studentId) {
if (isset($this->students[$studentId])) {
return array_sum($this->students[$studentId]["grades"]);
}
return 0;
}
// 获取班级排名
public function getClassRanking($class = null) {
$rankings = [];
foreach ($this->students as $student) {
if ($class === null || $student["class"] === $class) {
$totalScore = $this->getTotalScore($student["id"]);
$rankings[] = [
"id" => $student["id"],
"name" => $student["name"],
"class" => $student["class"],
"total_score" => $totalScore,
"average_score" => $totalScore / count($this->subjects)
];
}
}
// 按总分排序
usort($rankings, function($a, $b) {
return $b["total_score"] - $a["total_score"];
});
// 添加排名
foreach ($rankings as $index => &$ranking) {
$ranking["rank"] = $index + 1;
}
return $rankings;
}
// 获取科目统计
public function getSubjectStats() {
$stats = [];
foreach ($this->subjects as $subjectIndex => $subject) {
$scores = array_column($this->students, "grades");
$subjectScores = array_column($scores, $subjectIndex);
$stats[$subject] = [
"highest" => max($subjectScores),
"lowest" => min($subjectScores),
"average" => array_sum($subjectScores) / count($subjectScores),
"pass_rate" => count(array_filter($subjectScores, function($score) {
return $score >= 60;
})) / count($subjectScores) * 100
];
}
return $stats;
}
// 生成成绩单
public function generateReportCard($studentId) {
if (!isset($this->students[$studentId])) {
return null;
}
$student = $this->students[$studentId];
$totalScore = $this->getTotalScore($studentId);
$averageScore = $totalScore / count($this->subjects);
return [
"student_info" => [
"id" => $student["id"],
"name" => $student["name"],
"class" => $student["class"]
],
"subjects" => array_map(function($grade, $subject) {
return [
"name" => $subject,
"score" => $grade,
"level" => $this->getGradeLevel($grade)
];
}, $student["grades"], $this->subjects),
"summary" => [
"total_score" => $totalScore,
"average_score" => round($averageScore, 1),
"class_rank" => $this->getStudentRank($studentId),
"grade_level" => $this->getGradeLevel($averageScore)
],
"exam_history" => $student["exams"]
];
}
// 获取等级
private function getGradeLevel($score) {
if ($score >= 90) return "优秀";
if ($score >= 80) return "良好";
if ($score >= 70) return "中等";
if ($score >= 60) return "及格";
return "不及格";
}
// 获取学生排名
private function getStudentRank($studentId) {
$rankings = $this->getClassRanking($this->students[$studentId]["class"]);
foreach ($rankings as $ranking) {
if ($ranking["id"] == $studentId) {
return $ranking["rank"];
}
}
return 0;
}
// 显示班级排名
public function displayClassRanking($class = null) {
$rankings = $this->getClassRanking($class);
$title = $class ? "班级 {$class} 排名" : "全校排名";
echo "=== {$title} ===\n\n";
printf("%-5s %-10s %-10s %-10s %-10s %-10s\n",
"排名", "姓名", "班级", "总分", "平均分", "等级");
echo str_repeat("-", 60) . "\n";
foreach ($rankings as $ranking) {
printf("%-5d %-10s %-10s %-10d %-10.1f %-10s\n",
$ranking["rank"],
$ranking["name"],
$ranking["class"],
$ranking["total_score"],
$ranking["average_score"],
$this->getGradeLevel($ranking["average_score"])
);
}
}
}
// 使用示例
$gradeManager = new GradeManager();
// 添加学生
$students = [
["张三", "高三1班"],
["李四", "高三1班"],
["王五", "高三2班"],
["赵六", "高三2班"],
["钱七", "高三1班"]
];
foreach ($students as [$name, $class]) {
$gradeManager->addStudent($name, $class);
}
// 设置成绩
$grades = [
1 => [85, 92, 88, 90, 87],
2 => [78, 95, 82, 88, 91],
3 => [92, 88, 90, 85, 89],
4 => [80, 85, 78, 82, 80],
5 => [88, 91, 85, 89, 86]
];
foreach ($grades as $studentId => $studentGrades) {
foreach ($studentGrades as $subjectIndex => $grade) {
$gradeManager->setGrade($studentId, $subjectIndex, $grade);
}
}
// 添加考试成绩
$gradeManager->addExamResult(1, "期中考试", [82, 89, 85, 88, 84]);
$gradeManager->addExamResult(1, "期末考试", [87, 94, 90, 91, 88]);
// 显示排名
$gradeManager->displayClassRanking();
echo "\n";
// 显示特定班级排名
$gradeManager->displayClassRanking("高三1班");
echo "\n";
// 显示科目统计
$subjectStats = $gradeManager->getSubjectStats();
echo "=== 科目统计 ===\n";
foreach ($subjectStats as $subject => $stats) {
echo "{$subject}:\n";
echo " 最高分:{$stats['highest']}\n";
echo " 最低分:{$stats['lowest']}\n";
echo " 平均分:{$stats['average']:.1f}\n";
echo " 及格率:{$stats['pass_rate']:.1f}%\n\n";
}
// 生成成绩单
$reportCard = $gradeManager->generateReportCard(1);
echo "=== 学生成绩单 ===\n";
echo "学生:{$reportCard['student_info']['name']} ({$reportCard['student_info']['class']})\n\n";
echo "各科成绩:\n";
foreach ($reportCard['subjects'] as $subject) {
echo " {$subject['name']}:{$subject['score']}分 ({$subject['level']})\n";
}
echo "\n总分:{$reportCard['summary']['total_score']}分\n";
echo "平均分:{$reportCard['summary']['average_score']}分\n";
echo "班级排名:第{$reportCard['summary']['class_rank']}名\n";
echo "综合等级:{$reportCard['summary']['grade_level']}\n";
if (!empty($reportCard['exam_history'])) {
echo "\n考试历史:\n";
foreach ($reportCard['exam_history'] as $exam) {
echo " {$exam['exam_name']} ({$exam['date']}):";
echo "{$exam['total']}分 (平均{$exam['average']:.1f}分)\n";
}
}
?>
2. 电商库存管理系统
<?php
class InventoryManager {
private $warehouses = [];
private $products = [];
public function __construct() {
// 初始化仓库
$this->warehouses = [
"WH001" => ["name" => "北京仓库", "location" => "北京"],
"WH002" => ["name" => "上海仓库", "location" => "上海"],
"WH003" => ["name" => "广州仓库", "location" => "广州"]
];
// 初始化库存数据
foreach ($this->warehouses as $warehouseId => $warehouse) {
$this->products[$warehouseId] = [];
}
}
// 添加产品到仓库
public function addProduct($warehouseId, $productId, $productName, $quantity, $price) {
if (!isset($this->products[$warehouseId])) {
throw new Exception("仓库不存在");
}
if (isset($this->products[$warehouseId][$productId])) {
// 产品已存在,更新数量
$this->products[$warehouseId][$productId]["quantity"] += $quantity;
// 更新平均价格
$currentValue = $this->products[$warehouseId][$productId]["quantity"] *
$this->products[$warehouseId][$productId]["price"];
$newValue = $currentValue + ($quantity * $price);
$newQuantity = $this->products[$warehouseId][$productId]["quantity"] + $quantity;
$this->products[$warehouseId][$productId]["price"] = $newValue / $newQuantity;
} else {
// 新产品
$this->products[$warehouseId][$productId] = [
"name" => $productName,
"quantity" => $quantity,
"price" => $price,
"total_value" => $quantity * $price,
"last_updated" => date("Y-m-d H:i:s")
];
}
return true;
}
// 转移库存
public function transferStock($fromWarehouse, $toWarehouse, $productId, $quantity) {
if (!isset($this->products[$fromWarehouse][$productId])) {
throw new Exception("源仓库没有该产品");
}
if ($this->products[$fromWarehouse][$productId]["quantity"] < $quantity) {
throw new Exception("库存不足");
}
// 从源仓库移除
$this->products[$fromWarehouse][$productId]["quantity"] -= $quantity;
$this->products[$fromWarehouse][$productId]["total_value"] -=
$quantity * $this->products[$fromWarehouse][$productId]["price"];
$this->products[$fromWarehouse][$productId]["last_updated"] = date("Y-m-d H:i:s");
// 添加到目标仓库
$this->addProduct(
$toWarehouse,
$productId,
$this->products[$fromWarehouse][$productId]["name"],
$quantity,
$this->products[$fromWarehouse][$productId]["price"]
);
return true;
}
// 获取产品总库存
public function getTotalStock($productId) {
$total = 0;
$totalValue = 0;
$warehouses = [];
foreach ($this->products as $warehouseId => $products) {
if (isset($products[$productId])) {
$total += $products[$productId]["quantity"];
$totalValue += $products[$productId]["total_value"];
$warehouses[] = [
"warehouse_id" => $warehouseId,
"warehouse_name" => $this->warehouses[$warehouseId]["name"],
"quantity" => $products[$productId]["quantity"]
];
}
}
return [
"product_id" => $productId,
"total_quantity" => $total,
"total_value" => $totalValue,
"average_price" => $total > 0 ? $totalValue / $total : 0,
"distribution" => $warehouses
];
}
// 获取仓库库存汇总
public function getWarehouseSummary($warehouseId) {
if (!isset($this->products[$warehouseId])) {
return null;
}
$totalProducts = count($this->products[$warehouseId]);
$totalQuantity = 0;
$totalValue = 0;
foreach ($this->products[$warehouseId] as $product) {
$totalQuantity += $product["quantity"];
$totalValue += $product["total_value"];
}
return [
"warehouse_id" => $warehouseId,
"warehouse_name" => $this->warehouses[$warehouseId]["name"],
"location" => $this->warehouses[$warehouseId]["location"],
"product_count" => $totalProducts,
"total_quantity" => $totalQuantity,
"total_value" => $totalValue
];
}
// 获取库存预警
public function getLowStockAlerts($threshold = 10) {
$alerts = [];
foreach ($this->products as $warehouseId => $products) {
foreach ($products as $productId => $product) {
if ($product["quantity"] <= $threshold) {
$alerts[] = [
"warehouse_id" => $warehouseId,
"warehouse_name" => $this->warehouses[$warehouseId]["name"],
"product_id" => $productId,
"product_name" => $product["name"],
"current_quantity" => $product["quantity"],
"threshold" => $threshold
];
}
}
}
return $alerts;
}
// 生成库存报告
public function generateInventoryReport() {
$report = [
"generated_at" => date("Y-m-d H:i:s"),
"warehouses" => [],
"summary" => [
"total_warehouses" => count($this->warehouses),
"total_products" => 0,
"total_quantity" => 0,
"total_value" => 0
]
];
foreach ($this->warehouses as $warehouseId => $warehouse) {
$summary = $this->getWarehouseSummary($warehouseId);
if ($summary) {
$report["warehouses"][] = $summary;
$report["summary"]["total_products"] += $summary["product_count"];
$report["summary"]["total_quantity"] += $summary["total_quantity"];
$report["summary"]["total_value"] += $summary["total_value"];
}
}
return $report;
}
// 显示仓库详情
public function displayWarehouseDetails($warehouseId) {
if (!isset($this->products[$warehouseId])) {
echo "仓库不存在\n";
return;
}
$warehouse = $this->warehouses[$warehouseId];
echo "=== {$warehouse['name']} ({$warehouseId}) ===\n";
echo "位置:{$warehouse['location']}\n\n";
if (empty($this->products[$warehouseId])) {
echo "仓库为空\n";
return;
}
printf("%-15s %-20s %-10s %-10s %-15s\n",
"产品ID", "产品名称", "数量", "单价", "总价值");
echo str_repeat("-", 70) . "\n";
foreach ($this->products[$warehouseId] as $productId => $product) {
printf("%-15s %-20s %-10d %-10.2f %-15.2f\n",
$productId,
$product["name"],
$product["quantity"],
$product["price"],
$product["total_value"]
);
}
$summary = $this->getWarehouseSummary($warehouseId);
echo "\n仓库汇总:\n";
echo "产品种类:{$summary['product_count']} 种\n";
echo "总数量:{$summary['total_quantity']} 件\n";
echo "总价值:¥{$summary['total_value']:.2f}\n";
}
// 显示产品分布
public function displayProductDistribution($productId) {
$distribution = $this->getTotalStock($productId);
echo "=== 产品库存分布 ===\n";
echo "产品ID:{$distribution['product_id']}\n";
echo "总库存:{$distribution['total_quantity']} 件\n";
echo "总价值:¥{$distribution['total_value']:.2f}\n";
echo "平均价格:¥{$distribution['average_price']:.2f}\n\n";
echo "各仓库分布:\n";
foreach ($distribution['distribution'] as $warehouse) {
echo "- {$warehouse['warehouse_name']}:{$warehouse['quantity']} 件\n";
}
}
}
// 使用示例
$inventory = new InventoryManager();
// 添加产品到不同仓库
$inventory->addProduct("WH001", "P001", "iPhone 15", 50, 5999);
$inventory->addProduct("WH001", "P002", "MacBook Pro", 20, 14999);
$inventory->addProduct("WH002", "P001", "iPhone 15", 30, 5999);
$inventory->addProduct("WH002", "P003", "AirPods", 100, 1999);
$inventory->addProduct("WH003", "P002", "MacBook Pro", 15, 14999);
$inventory->addProduct("WH003", "P004", "iPad", 40, 3999);
// 显示各仓库详情
foreach (["WH001", "WH002", "WH003"] as $warehouseId) {
$inventory->displayWarehouseDetails($warehouseId);
echo "\n";
}
// 显示产品分布
$inventory->displayProductDistribution("P001");
echo "\n";
// 库存转移
try {
$inventory->transferStock("WH001", "WH002", "P001", 10);
echo "成功转移10个iPhone 15从北京仓库到上海仓库\n\n";
$inventory->displayProductDistribution("P001");
} catch (Exception $e) {
echo "转移失败:" . $e->getMessage() . "\n";
}
// 库存预警
$alerts = $inventory->getLowStockAlerts(25);
if (!empty($alerts)) {
echo "=== 库存预警 ===\n";
foreach ($alerts as $alert) {
echo "仓库:{$alert['warehouse_name']}\n";
echo "产品:{$alert['product_name']} ({$alert['product_id']})\n";
echo "当前库存:{$alert['current_quantity']} (阈值:{$alert['threshold']})\n\n";
}
} else {
echo "无库存预警\n";
}
// 生成完整报告
$report = $inventory->generateInventoryReport();
echo "=== 库存总报告 ===\n";
echo "生成时间:{$report['generated_at']}\n";
echo "总仓库数:{$report['summary']['total_warehouses']}\n";
echo "总产品种类:{$report['summary']['total_products']}\n";
echo "总库存量:{$report['summary']['total_quantity']} 件\n";
echo "总库存价值:¥{$report['summary']['total_value']:.2f}\n";
?>
3. 数据分析工具
<?php
class DataAnalyzer {
private $data = [];
// 加载数据
public function loadData($data) {
$this->data = $data;
}
// 从CSV文件加载数据
public function loadFromCSV($filename) {
if (!file_exists($filename)) {
throw new Exception("文件不存在");
}
$this->data = [];
$handle = fopen($filename, 'r');
// 读取表头
$headers = fgetcsv($handle);
// 读取数据行
while (($row = fgetcsv($handle)) !== false) {
$this->data[] = array_combine($headers, $row);
}
fclose($handle);
}
// 获取数据概览
public function getDataOverview() {
if (empty($this->data)) {
return null;
}
$overview = [
"total_rows" => count($this->data),
"columns" => array_keys($this->data[0]),
"column_info" => []
];
foreach ($overview["columns"] as $column) {
$values = array_column($this->data, $column);
$numericValues = array_filter($values, function($value) {
return is_numeric($value);
});
$overview["column_info"][$column] = [
"type" => count($numericValues) > 0 ? "numeric" : "text",
"null_count" => count(array_filter($values, function($value) {
return $value === null || $value === '';
})),
"unique_values" => count(array_unique($values))
];
if ($overview["column_info"][$column]["type"] === "numeric") {
$numericValues = array_map('floatval', $numericValues);
$overview["column_info"][$column]["min"] = min($numericValues);
$overview["column_info"][$column]["max"] = max($numericValues);
$overview["column_info"][$column]["average"] = array_sum($numericValues) / count($numericValues);
}
}
return $overview;
}
// 按列分组统计
public function groupBy($column, $valueColumn = null) {
if (empty($this->data)) {
return [];
}
$groups = [];
foreach ($this->data as $row) {
$key = $row[$column] ?? 'Unknown';
if (!isset($groups[$key])) {
$groups[$key] = [
"count" => 0,
"values" => [],
"rows" => []
];
}
$groups[$key]["count"]++;
$groups[$key]["rows"][] = $row;
if ($valueColumn && isset($row[$valueColumn]) && is_numeric($row[$valueColumn])) {
$groups[$key]["values"][] = floatval($row[$valueColumn]);
}
}
// 计算统计信息
foreach ($groups as $key => &$group) {
if (!empty($group["values"])) {
$group["sum"] = array_sum($group["values"]);
$group["average"] = $group["sum"] / count($group["values"]);
$group["min"] = min($group["values"]);
$group["max"] = max($group["values"]);
}
}
return $groups;
}
// 数据透视表
public function pivotTable($indexColumn, $columnColumn, $valueColumn, $aggregation = 'sum') {
if (empty($this->data)) {
return [];
}
$pivot = [];
$columnValues = [];
// 收集所有列值
foreach ($this->data as $row) {
$colValue = $row[$columnColumn] ?? 'Unknown';
if (!in_array($colValue, $columnValues)) {
$columnValues[] = $colValue;
}
}
// 初始化透视表
foreach ($this->data as $row) {
$indexValue = $row[$indexColumn] ?? 'Unknown';
if (!isset($pivot[$indexValue])) {
$pivot[$indexValue] = array_fill_keys($columnValues, 0);
}
$colValue = $row[$columnColumn] ?? 'Unknown';
$value = isset($row[$valueColumn]) && is_numeric($row[$valueColumn])
? floatval($row[$valueColumn]) : 0;
switch ($aggregation) {
case 'sum':
$pivot[$indexValue][$colValue] += $value;
break;
case 'count':
$pivot[$indexValue][$colValue]++;
break;
case 'average':
// 平均值需要特殊处理
if (!isset($pivot[$indexValue][$colValue . '_sum'])) {
$pivot[$indexValue][$colValue . '_sum'] = 0;
$pivot[$indexValue][$colValue . '_count'] = 0;
}
$pivot[$indexValue][$colValue . '_sum'] += $value;
$pivot[$indexValue][$colValue . '_count']++;
$pivot[$indexValue][$colValue] = $pivot[$indexValue][$colValue . '_sum'] /
$pivot[$indexValue][$colValue . '_count'];
break;
}
}
// 清理临时数据
if ($aggregation === 'average') {
foreach ($pivot as &$row) {
foreach ($row as $key => $value) {
if (strpos($key, '_sum') !== false || strpos($key, '_count') !== false) {
unset($row[$key]);
}
}
}
}
return $pivot;
}
// 数据筛选
public function filter($conditions) {
return array_filter($this->data, function($row) use ($conditions) {
foreach ($conditions as $column => $condition) {
$value = $row[$column] ?? null;
if (is_array($condition)) {
// 范围条件 ['min' => 10, 'max' => 100]
if (isset($condition['min']) && $value < $condition['min']) {
return false;
}
if (isset($condition['max']) && $value > $condition['max']) {
return false;
}
if (isset($condition['in']) && !in_array($value, $condition['in'])) {
return false;
}
} else {
// 精确匹配
if ($value != $condition) {
return false;
}
}
}
return true;
});
}
// 数据排序
public function sort($columns, $order = 'asc') {
$sortedData = $this->data;
usort($sortedData, function($a, $b) use ($columns, $order) {
foreach ($columns as $column) {
$aValue = $a[$column] ?? 0;
$bValue = $b[$column] ?? 0;
if ($aValue != $bValue) {
$result = $aValue <=> $bValue;
return $order === 'desc' ? -$result : $result;
}
}
return 0;
});
return $sortedData;
}
// 显示数据表格
public function displayTable($data = null, $limit = 10) {
$displayData = $data ?? $this->data;
if (empty($displayData)) {
echo "没有数据可显示\n";
return;
}
$columns = array_keys($displayData[0]);
$displayCount = min($limit, count($displayData));
// 计算列宽
$columnWidths = [];
foreach ($columns as $column) {
$columnWidths[$column] = strlen($column);
}
for ($i = 0; $i < $displayCount; $i++) {
foreach ($columns as $column) {
$value = (string)($displayData[$i][$column] ?? '');
$columnWidths[$column] = max($columnWidths[$column], strlen($value));
}
}
// 显示表头
foreach ($columns as $column) {
printf("%-{$columnWidths[$column]}s ", $column);
}
echo "\n";
// 显示分隔线
foreach ($columns as $column) {
echo str_repeat("-", $columnWidths[$column]) . " ";
}
echo "\n";
// 显示数据行
for ($i = 0; $i < $displayCount; $i++) {
foreach ($columns as $column) {
$value = (string)($displayData[$i][$column] ?? '');
printf("%-{$columnWidths[$column]}s ", $value);
}
echo "\n";
}
if ($displayCount < count($displayData)) {
echo "\n... 显示前 {$displayCount} 行,共 " . count($displayData) . " 行\n";
}
}
}
// 使用示例
$analyzer = new DataAnalyzer();
// 创建示例销售数据
$salesData = [
["date" => "2023-01-01", "region" => "北京", "product" => "iPhone", "sales" => 120, "revenue" => 719880],
["date" => "2023-01-01", "region" => "上海", "product" => "iPhone", "sales" => 98, "revenue" => 587902],
["date" => "2023-01-01", "region" => "广州", "product" => "MacBook", "sales" => 45, "revenue" => 674955],
["date" => "2023-01-02", "region" => "北京", "product" => "MacBook", "sales" => 38, "revenue" => 569962],
["date" => "2023-01-02", "region" => "上海", "product" => "iPad", "sales" => 67, "revenue" => 267933],
["date" => "2023-01-02", "region" => "广州", "product" => "iPhone", "sales" => 85, "revenue" => 509915],
["date" => "2023-01-03", "region" => "北京", "product" => "iPad", "sales" => 52, "revenue" => 207948],
["date" => "2023-01-03", "region" => "上海", "product" => "MacBook", "sales" => 42, "revenue" => 629958],
["date" => "2023-01-03", "region" => "广州", "product" => "iPad", "sales" => 61, "revenue" => 243939]
];
$analyzer->loadData($salesData);
echo "=== 数据概览 ===\n";
$overview = $analyzer->getDataOverview();
echo "总行数:{$overview['total_rows']}\n";
echo "列数:" . count($overview['columns']) . "\n";
echo "列名:" . implode(", ", $overview['columns']) . "\n\n";
echo "=== 列信息 ===\n";
foreach ($overview['column_info'] as $column => $info) {
echo "{$column}:\n";
echo " 类型:{$info['type']}\n";
echo " 空值数:{$info['null_count']}\n";
echo " 唯一值数:{$info['unique_values']}\n";
if ($info['type'] === 'numeric') {
echo " 最小值:{$info['min']}\n";
echo " 最大值:{$info['max']}\n";
echo " 平均值:{$info['average']:.2f}\n";
}
echo "\n";
}
echo "=== 原始数据表格 ===\n";
$analyzer->displayTable(null, 5);
echo "\n=== 按地区分组统计 ===\n";
$regionGroups = $analyzer->groupBy("region", "revenue");
foreach ($regionGroups as $region => $group) {
echo "{$region}:\n";
echo " 记录数:{$group['count']}\n";
echo " 总收入:¥{$group['sum']:,.0f}\n";
echo " 平均收入:¥{$group['average']:,.0f}\n";
echo " 最高收入:¥{$group['max']:,.0f}\n";
echo " 最低收入:¥{$group['min']:,.0f}\n\n";
}
echo "=== 产品销售透视表(按地区) ===\n";
$pivotTable = $analyzer->pivotTable("region", "product", "sales", "sum");
// 显示透视表
$products = array_unique(array_column($salesData, 'product'));
$regions = array_unique(array_column($salesData, 'region'));
printf("%-10s", "地区\\产品");
foreach ($products as $product) {
printf("%-10s", $product);
}
echo "\n";
foreach ($regions as $region) {
printf("%-10s", $region);
foreach ($products as $product) {
$sales = $pivotTable[$region][$product] ?? 0;
printf("%-10d", $sales);
}
echo "\n";
}
echo "\n=== 筛选数据(收入大于500000) ===\n";
$filtered = $analyzer->filter(["revenue" => ["min" => 500000]]);
$analyzer->displayTable($filtered);
echo "\n=== 按收入排序 ===\n";
$sorted = $analyzer->sort(["revenue"], "desc");
$analyzer->displayTable($sorted, 5);
?>
常见错误和解决方案
1. 数组维度错误
// 错误:试图访问不存在的维度
$data = [[1, 2], [3, 4]];
echo $data[0][2]; // Notice: Undefined offset
// 正确做法:检查数组维度
function getNestedValue($array, $path) {
$current = $array;
foreach ($path as $key) {
if (!is_array($current) || !array_key_exists($key, $current)) {
return null;
}
$current = $current[$key];
}
return $current;
}
$value = getNestedValue($data, [0, 1]); // 安全访问
2. 引用传递问题
// 错误:意外修改原数组
$original = [[1, 2], [3, 4]];
$copy = $original;
$copy[0][0] = 99; // $original也会被修改
// 正确做法:深拷贝
$deepCopy = json_decode(json_encode($original), true);
$deepCopy[0][0] = 99; // 只影响副本
3. 内存使用问题
// 不好的做法:创建过大的数组
$hugeArray = [];
for ($i = 0; $i < 1000000; $i++) {
$hugeArray[$i] = range(0, 100); // 可能导致内存不足
}
// 好的做法:使用生成器或分批处理
function processLargeData($count) {
for ($i = 0; $i < $count; $i++) {
yield range($i, $i + 100);
}
}
foreach (processLargeData(1000000) as $batch) {
// 分批处理数据
}
性能优化建议
1. 选择合适的数据结构
// 对于频繁查找的操作,使用关联数组比多维数组更高效
// 不好的做法
$users = [
[1, "张三", "zhangsan@example.com"],
[2, "李四", "lisi@example.com"]
];
// 好的做法
$users = [
1 => ["name" => "张三", "email" => "zhangsan@example.com"],
2 => ["name" => "李四", "email" => "lisi@example.com"]
];
// 查找时O(1)时间复杂度
$user = $users[1] ?? null;
2. 避免深层嵌套
// 不好的做法:过深的嵌套
$config["database"]["connections"]["mysql"]["settings"]["timeout"] = 30;
// 好的做法:适当的扁平化
$config["mysql_timeout"] = 30;
// 或者使用配置类来管理
3. 使用内置函数
// 不好的做法:手动循环
$totals = [];
foreach ($data as $row) {
$category = $row['category'];
if (!isset($totals[$category])) {
$totals[$category] = 0;
}
$totals[$category] += $row['amount'];
}
// 好的做法:使用内置函数
$totals = array_reduce($data, function($carry, $item) {
$carry[$item['category']] = ($carry[$item['category']] ?? 0) + $item['amount'];
return $carry;
}, []);
练习题
基础练习
-
创建和访问多维数组
// 创建一个3x3的乘法表 // 访问特定行和列的值 // 计算对角线元素的和 -
二维数组操作
// 创建学生成绩表 // 计算每个学生的总分和平均分 // 找出每科的最高分
进阶练习
-
矩阵操作
// 实现矩阵加法和乘法 // 计算矩阵的转置 // 实现矩阵的行列式计算 -
数据透视
// 将销售数据转换为透视表 // 按多个维度分组统计 // 实现动态的透视表生成
实战练习
-
简单的电子表格
// 使用多维数组实现电子表格 // 支持基本的单元格操作 // 实现行和列的计算功能 -
游戏地图编辑器
// 使用二维数组表示游戏地图 // 实现地图的加载、保存和编辑 // 支持图层和对象放置
总结
多维数组是PHP中处理复杂数据结构的重要工具。通过本节的学习,你应该:
- 理解多维数组的概念和应用场景
- 掌握创建、访问和修改多维数组的方法
- 熟练遍历和操作多维数组的技巧
- 了解多维数组在实际项目中的应用
- 能够优化多维数组的性能和内存使用
多维数组是数组学习的进阶内容,掌握好它将让你能够处理更加复杂和层次化的数据结构,为开发复杂的PHP应用打下坚实基础。
接下来,我们将学习常用的数组函数,这将进一步提升我们处理数组的能力。