
本文介绍如何在 php 中根据匹配条件筛选 csv 数据后,**动态识别并移除每行中值为 0 的数值列(如鞋码库存)**,同时同步精简表头,实现“按行定制化列结构”的灵活处理。
在实际业务场景中(例如鞋类库存导出),CSV 文件常包含大量尺寸列(如 31–38),但不同商品仅在部分尺码有库存。若直接导出全部列,会带来冗余和可读性问题。理想的处理方式是:对每一匹配行,仅保留库存 > 0 的尺寸列,并动态生成对应的精简表头与数据行。
上述需求可通过 array_combine() + array_filter() 组合高效实现。关键在于:将表头($keys)与当前数据行($line)配对成关联数组,再利用 array_filter() 默认行为(过滤掉 0、""、null、false 等 falsy 值)剔除库存为 0 的项——这正是本方案的核心逻辑。
以下是优化后的完整代码段(含健壮性增强):
$csvContent = file_get_contents($_SERVER['DOCUMENT_ROOT'] . '/CsvTest/Sortiment.csv');
$input = 'Company';
$value = 'Dockers';
// 解析 CSV:按行分割 → 拆分为 CSV 数组
$rows = array_map('str_getcsv', explode(PHP_EOL, trim($csvContent)));
if (empty($rows)) {
throw new RuntimeException('CSV is empty or malformed.');
}
$keys = array_shift($rows); // 提取表头
$keyIndex = array_search($input, $keys);
if ($keyIndex === false) {
throw new InvalidArgumentException("Column '{$input}' not found in CSV header.");
}
$sortiment_array = [];
foreach ($rows as $line) {
// 跳过空行或无效行
if (!is_array($line) || count($line) !== count($keys)) continue;
if (isset($line[$keyIndex]) && $line[$keyIndex] === $value) {
// 关键步骤:用表头与数据行构建关联数组,并过滤掉值为 0(及其它 falsy)的项
$combined = array_combine($keys, $line);
// 注意:array_filter 会保留键名,且默认过滤 falsy 值(0 会被移除)
$filtered = array_filter($combined, function($v) {
// 显式判断:只过滤严格等于字符串 "0" 或整数 0,避免误删 "0.5"、"001" 等
return $v !== '0' && $v !== 0 && $v !== '';
});
$sortiment_array[] = [
'shoe size' => implode(',', array_keys($filtered)),
'sortiment' => implode(',', $filtered)
];
}
}✅ 输出效果示例(对应原始数据中两行 Dockers):
立即学习“PHP免费学习笔记(深入)”;
array(2) {
[0] => array(2) {
["shoe size"] => string(42) "Company,Produkt,Sortiment name,31,32,33,34,35,36"
["sortiment"] => string(37) "Dockers,AD1234,Sort A,2,3,5,3,2,1"
}
[1] => array(2) {
["shoe size"] => string(45) "Company,Produkt,Sortiment name,32,33,34,35,36,38"
["sortiment"] => string(37) "Dockers,AE1234,Sort D,1,2,3,4,1,2"
}
}⚠️ 注意事项:
- array_filter() 默认会移除所有 falsy 值(包括 0, "", null, false)。若 CSV 中存在合法的空字符串(如未填写的备注字段)或需保留 "0" 字符串(非数值零),请务必使用显式回调函数(如上所示)进行精准判断。
- 确保 $keys 与 $line 长度一致,否则 array_combine() 将返回 false;建议添加 count() 校验。
- 若需支持多匹配值(如 ['Dockers', 'Nike']),可将 $value 改为数组,并用 in_array($line[$keyIndex], $values) 替代严格相等判断。
该方案简洁、高效、可扩展,完美契合“按行动态裁剪列”的典型数据清洗需求。











