读取包含键值对行的 csv 文件,用于创建一个新的 csv 文件,该文件的标题中包含唯一键,行中包含默认值

问题描述 投票:0回答:2

我有一个特定格式的 CSV 数据集

key=value,key2=value,key3=value
key=value,key2=value,key4=value,key3=value

我想将其转换为:

key,key2,key3,key4
value,value,value,null
value,value,value,value

但是输出 csv 中存在数组不匹配。

我需要对标题列进行排序,确保后续行值位于右列中,如果缺少给定列值,请使用字符串

null

这是我的编码尝试:

if (($handle = fopen("sheet4.csv", "r")) !== FALSE) {
    while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
        $cols = explode(",", $data[0]);
        $num = count($cols);
        for ($c = 0; $c < $num; $c++) {
            $colData = explode("=", $cols[$c]);
            $outputHeaders[$row][$colData[0]] = $colData[0];
            $output[$row][$colData[0]] = $colData[1];
        }
        $csvOutput[$row] = array_combine($outputHeaders[$row], $output[$row]);
        $row++;
    }
    fclose($handle);
}

foreach ($csvOutput as $row => $rowData) {
    $extractHeaders[] = array_keys($rowData);
}

$mergedHeaders = array_unique(call_user_func_array('array_merge', $extractHeaders));

$fp = fopen('sheet4out.csv', 'wa');
fputcsv($fp, $mergedHeaders);
foreach ($csvOutput as $key => $fields) {
    $rowKeys = array_keys($fields);
    if (count($mergedHeaders) == count($rowKeys)) {
    } else {
        $differntKeys = array_diff($mergedHeaders, $rowKeys);
        $fields = array_merge($fields, array_fill_keys($differntKeys, 'banana'));
    }
    fputcsv($fp, $fields);
}
php arrays csv text-parsing csv-header
2个回答
0
投票

你不应该打电话给

explode(',', $data[0])
fgetcsv()
已经分解了该行,因此
$data[0]
只是第一个字段。

在读取输入 CSV 时,只需将每个字段名称添加到 headers 数组中即可。您可以通过在每行之后调用

array_unique()
来保持较小的值。

创建输出行时,您可以使用空合并运算符提供

null
作为行中缺失键的默认值。

$headers = [];
$rows = [];
if ($handle = fopen("sheet4.csv", "r")) {
    while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
        $row = [];
        foreach ($data as $field) {
            [$key, $value] = explode('=', $field);
            $row[$key] = $value;
        }
        $headers = array_unique(array_merge($headers, array_keys($row)));
        $rows[] = $row;
    }
    fclose($handle);
}

array_sort($headers);

if ($fp = fopen('sheet4out.csv', 'w')) {
    fputcsv($fp, $headers);
    foreach ($rows as $row) {
        $outrow = array_map(fn($field) => $row[$field] ?? 'null', $headers)
        fputcsv($fp, $outrow);
    }
}

0
投票
  • 以“读取”模式打开数据源文件。
  • 解析每一行并从分隔的键值对构建关联数组的索引数组,并构建遇到的键的平面关联数组——这将确保唯一性。
  • 关闭源文件,因为不再需要它。
  • 以“写入”模式打开一个新文件。如果文件已经存在,
    w
    将覆盖整个文件;如果文件已存在,
    a
    会将新数据追加到末尾。使用
    wa
    没有意义,使用
    w
  • 对标题进行排序(以您想要的任何方式)
  • 声明一个空值关联数组,以便在迭代时对每行的列数据进行排序,并确保所有列都有一个值。
  • 迭代时填充新值,然后关闭文件。

代码:(简化演示

$header = [];
$rows = [];
$fileHandle = fopen("sheet4.csv", "r");
while (($line = fgetcsv($fileHandle)) !== false) {
    foreach ($line as $pair) {
        [$key, $rows[$i][$key]] = explode('=', $line, 2);
        $header[$key] = $key;
    }
}
fclose($fileHandle);

sort($header);
$defaults = array_fill_keys($header, 'null');

$fileHandle = fopen('sheet4out.csv', 'w');
fputcsv($fileHandle, $header);
foreach ($rows as $row) {
    fputcsv($fileHandle, array_replace($defaults, $row));
}
fclose($fileHandle);
© www.soinside.com 2019 - 2024. All rights reserved.