
本文介绍如何将形如“dd.mm.yyyy|x,xxx”格式的日期-数值字符串解析为数组,并按年月分组计算各月数值的算术平均值,涵盖字符串拆分、日期提取、千位符清理与分组聚合等关键步骤。
本文介绍如何将形如“dd.mm.yyyy|x,xxx”格式的日期-数值字符串解析为数组,并按年月分组计算各月数值的算术平均值,涵盖字符串拆分、日期提取、千位符清理与分组聚合等关键步骤。
在实际数据处理中,常遇到以空格分隔、每项含日期与数值(用竖线 | 连接)的紧凑字符串,例如:
04.01.2021|26,140 05.01.2021|26,225 06.01.2021|26,145 11.02.2021|26,240 12.02.2021|26,190
目标是:按 MM.YYYY(如 01.2021)归类所有数值,去除逗号,再计算每月的算术平均值。整个流程可清晰划分为三步:字符串结构化解析 → 按月分组聚合 → 分组均值计算。
✅ 第一步:多级拆分构建二维结构
使用嵌套 explode() 配合 array_map(),先按空格切分记录,再对每条记录按 | 拆分为 [日期, 数值] 对:
$input = '04.01.2021|26,140 05.01.2021|26,225 06.01.2021|26,145 07.01.2021|26,145 08.01.2021|26,165 11.02.2021|26,240 12.02.2021|26,190';
$records = array_map(
fn($item) => explode('|', trim($item)),
explode(' ', $input)
);
// $records 现为二维数组:[['04.01.2021','26,140'], ['05.01.2021','26,225'], ...]
⚠️ 注意:务必对 $item 使用 trim(),避免首尾空格导致解析异常(尤其当输入前后有空格时)。
✅ 第二步:按 MM.YYYY 分组并清洗数值
利用 array_reduce() 构建以 MM.YYYY 为键的关联数组,同时用 substr($date, 3) 提取日期子串(跳过日部分 DD.),并用 str_replace(',', '', $value) 移除千位逗号,确保数值可参与数学运算:
$groupedByMonth = array_reduce(
$records,
function ($carry, $item) {
[$date, $value] = $item;
$monthKey = substr($date, 3); // → "01.2021", "02.2021"
$cleanValue = (float) str_replace(',', '', $value);
$carry[$monthKey][] = $cleanValue;
return $carry;
},
[]
);
// 结果示例:
// [
// '01.2021' => [26140.0, 26225.0, 26145.0, 26145.0, 26165.0],
// '02.2021' => [26240.0, 26190.0]
// ]
? 提示:此处强制转换为 (float) 更安全——若原始数值含小数(如 26,140.5),仅 str_replace() 不足以保证精度;但本例中逗号仅为千位符,故 float 或 int 均可,推荐 float 以兼容未来扩展。
✅ 第三步:计算每月均值
对 $groupedByMonth 的每个子数组,调用 array_sum() / count() 即得算术平均值。使用 array_map() 保持函数式风格:
$averagesPerMonth = array_map(
fn($values) => round(array_sum($values) / count($values), 2),
$groupedByMonth
);
print_r($averagesPerMonth);
// 输出:
// Array
// (
// [01.2021] => 26164
// [02.2021] => 26215
// )
? round(..., 2) 可选:若原始数据为整数且无需小数,可省略;若需保留两位小数(如货币场景),建议显式指定。
✅ 完整可运行示例(含错误防护)
function calculateMonthlyAverage(string $input): array {
if (empty($input)) {
return [];
}
$records = array_map(
fn($item) => explode('|', trim($item)),
array_filter(explode(' ', $input)) // 过滤空元素,增强鲁棒性
);
$groupedByMonth = array_reduce(
$records,
function ($carry, $item) {
if (count($item) !== 2) return $carry; // 跳过格式异常项
[$date, $value] = $item;
if (!preg_match('/^\d{2}\.\d{2}\.\d{4}$/', $date)) return $carry;
$monthKey = substr($date, 3);
$cleanValue = (float) str_replace(',', '', $value);
$carry[$monthKey][] = $cleanValue;
return $carry;
},
[]
);
return array_map(
fn($values) => round(array_sum($values) / count($values), 2),
$groupedByMonth
);
}
// 使用
$result = calculateMonthlyAverage($input);
print_r($result);
总结:该方案以 explode 为起点,通过函数式链式操作(array_map → array_reduce → array_map)实现高内聚、低耦合的数据流处理。核心在于明确每步的中间数据形态,并针对性地清洗与转换。适用于日志分析、金融数据汇总等需按时间维度聚合的典型场景。










