我正在使用
league/csv:^9.6
(9.6.2)。
我需要解析包含大量列(150+)的 CSV 文件,并提取其中的少量列(8)。这些列在偏移量方面并不固定(位置未知),但它们具有稳定的唯一标题 - 所以我想通过标题而不是偏移量来选择它们。
但问题是:库抛出有关重复标头的异常。有没有解决方案如何跳过它们并正确解析所有其他行?
或者有什么解决方法可以在使用这个库之前将它们从文件中删除吗?这些重复项的位置和数量事先是未知的。
谢谢!
您可以自己映射列名称。不要设置标题偏移量,这将使 League 返回带有整数键的行。
然后使用包含所需列名的数组来构建索引的映射。我做了一个小工作示例:
测试.csv
name;;;age;;;;a;a;a;;;;
John;;;32;;;;;;;;;;
Jane;;;28;;;;;;;;;;
测试.php
//The columns you want to extract
$columns = ['name', 'age'];
$reader = Reader::createFromPath('test.csv', 'r+');
$reader->setDelimiter(';');
$grab = [];
//Find the indexes
foreach ($reader->fetchOne() as $index => $column) {
if (in_array($column, $columns)) {
$grab[$column] = $index;
}
}
foreach ($reader->getRecords() as $i => $row) {
if ($i == 0) {
continue;
}
$filteredRow = [];
foreach ($grab as $column => $index) {
$filteredRow[$column] = $row[$index];
}
//$filteredRow now contains the needed columns
var_dump($filteredRow);
}
输出:
array(2) {
["name"]=> string(4) "John"
["age"]=> string(2) "32"
}
array(2) {
["name"]=> string(4) "Jane"
["age"]=> string(2) "28"
}
简化版!
$columns = ['name', 'age'];
$validColumns = array_intersect($reader->fetchOne(0), $columns);
$validIndices = array_flip(array_keys($validColumns));
foreach ($reader->getRecords() as $i => $row) {
if ($i > 0) {
$csvArray[] = array_combine( $validColumns, array_intersect_key( $row, $validIndices ));
}
}
use League\Csv\Reader;
use League\Csv\Statement;
$reader = Reader::createFromString($csv);
$reader->setDelimiter(';');
$reader->setHeaderOffset(0);
$reader->setEscape('');
$records = Statement::create()
->process($reader, array_filter($reader->getHeader()));