如何用多维数组实现Excel SUBTOTAL函数功能及分组求和
实现多维数组分组求和(类似Excel SUBTOTAL功能)
嘿,我来帮你搞定这个需求!要实现类似Excel SUBTOTAL的分组统计功能,针对你的$products多维数组按Id分组计算求和值,咱们用PHP就能轻松实现,下面一步步来:
基础版:按Id分组求和Quantity和Price
首先,先把你的$products数组补全(假设剩下的项是合理的测试数据):
$products = array( array("Id" => "000001", "Name" => "Cheese", "Quantity" => "10", "Price" => "10"), array("Id" => "000001", "Name" => "Cheese", "Quantity" => "20", "Price" => "20"), array("Id" => "000001", "Name" => "Cheese", "Quantity" => "10", "Price" => "30"), array("Id" => "000002", "Name" => "Ham", "Quantity" => "20", "Price" => "200"), array("Id" => "000002", "Name" => "Ham", "Quantity" => "15", "Price" => "180"), array("Id" => "000003", "Name" => "Bread", "Quantity" => "50", "Price" => "5") );
然后是核心的分组求和代码:
// 初始化空数组存储分组结果 $groupedSummary = []; foreach ($products as $item) { $productId = $item["Id"]; // 关键:把字符串类型的数值转成数字,避免字符串拼接错误 $quantity = (int)$item["Quantity"]; $price = (float)$item["Price"]; // 如果当前Id还没在结果数组里,先初始化基础信息 if (!isset($groupedSummary[$productId])) { $groupedSummary[$productId] = [ "Id" => $productId, "Name" => $item["Name"], "TotalQuantity" => 0, "TotalPrice" => 0.0 ]; } // 累加数量和价格 $groupedSummary[$productId]["TotalQuantity"] += $quantity; $groupedSummary[$productId]["TotalPrice"] += $price; } // 转成和原数组一致的索引数组格式(可选) $finalResult = array_values($groupedSummary); // 输出结果看看 print_r($finalResult);
这段代码的逻辑很直观:
- 遍历每个产品项,提取关键字段并转成正确的数字类型(这一步很重要,不然字符串相加会变成拼接)
- 对每个
Id做判断,第一次出现时初始化汇总项 - 不断累加相同
Id的Quantity和Price值 - 最后用
array_values()把关联数组转成索引数组,和原数组格式统一
进阶版:封装成类似SUBTOTAL的通用函数
如果你需要像Excel SUBTOTAL那样支持多种统计方式(比如计数、平均值、最大值、最小值),可以封装一个通用函数,这样复用性更强:
function groupSubtotal($sourceArray, $groupField, $calcFields, $function = 'sum') { $result = []; foreach ($sourceArray as $item) { $groupKey = $item[$groupField]; // 初始化分组项,保留原字段 if (!isset($result[$groupKey])) { $result[$groupKey] = $item; // 给每个要统计的字段初始化对应类型的初始值 foreach ($calcFields as $field) { $totalKey = "Total" . ucfirst($field); switch ($function) { case 'sum': case 'count': $result[$groupKey][$totalKey] = 0; break; case 'avg': $result[$groupKey][$totalKey] = []; break; case 'max': case 'min': $result[$groupKey][$totalKey] = null; break; } } } // 根据选择的统计方式处理每个字段 foreach ($calcFields as $field) { $totalKey = "Total" . ucfirst($field); $value = is_numeric($item[$field]) ? (float)$item[$field] : 0; switch ($function) { case 'sum': $result[$groupKey][$totalKey] += $value; break; case 'count': $result[$groupKey][$totalKey]++; break; case 'avg': $result[$groupKey][$totalKey][] = $value; break; case 'max': if ($result[$groupKey][$totalKey] === null || $value > $result[$groupKey][$totalKey]) { $result[$groupKey][$totalKey] = $value; } break; case 'min': if ($result[$groupKey][$totalKey] === null || $value < $result[$groupKey][$totalKey]) { $result[$groupKey][$totalKey] = $value; } break; } } } // 如果是平均值统计,最后计算平均值 if ($function === 'avg') { foreach ($result as &$groupItem) { foreach ($calcFields as $field) { $totalKey = "Total" . ucfirst($field); $values = $groupItem[$totalKey]; $groupItem[$totalKey] = count($values) > 0 ? array_sum($values) / count($values) : 0; } } } // 转成索引数组返回 return array_values($result); } // 调用示例:按Id分组,求Quantity和Price的总和 $sumResult = groupSubtotal($products, "Id", ["Quantity", "Price"], 'sum'); print_r($sumResult); // 调用示例:按Id分组,求Price的平均值 $avgResult = groupSubtotal($products, "Id", ["Price"], 'avg'); print_r($avgResult);
这个函数可以灵活支持多种统计场景,完全对标Excel SUBTOTAL的不同功能选项,你可以根据需求选择对应的统计方式。
内容的提问来源于stack exchange,提问作者Carmen B.
相关产品推荐
相关产品推荐

