Процесс CSV в массив с заголовками столбцов для ключа

У меня есть CSV с первой строкой, содержащей имена полей. Пример данных …

"Make","Model","Note" "Chevy","1500","loaded" "Chevy","2500","" "Chevy","","loaded" 

Мне нужны мои данные, отформатированные в массиве пар ключ-значение, где ключевым именем является заголовок столбца. Думаю, для строки 1 это было бы примерно так:

 $array = [ "Make" => "Chevy", "Model" => "1500", "Note" => "loaded" ]; 

… строка 2 …

 $array = [ "Make" => "Chevy", "Model" => "1500", "Note" => "" ]; 

… и ряд 3 …

 $array = [ "Make" => "Chevy", "Model" => "", "Note" => "loaded" ]; 

Я не уверен, как это сделать, кроме статически. Проблема заключается в том, что столбцы со связанными с ними данными могут меняться от одного файла к другому … столбцы переупорядочиваются, удаляются или добавляются.

Вы очень цените идеи.

 $all_rows = array(); $header = fgetcsv($file); while ($row = fgetcsv($file)) { $all_rows[] = array_combine($header, $row); } 
 print_r($all_rows); 

PHP предлагает уже 99,9% того, что вам нужно в SplFileObject , вы добавляете недостающие 0,1%, расширяясь от него. В следующем примере CSVFile простирается от него:

 $csv = new CSVFile('../data/test.csv'); foreach ($csv as $line) { var_dump($line); } 

С примерами данных:

 array(3) { ["Make"]=> string(5) "Chevy" ["Model"]=> string(4) "1500" ["Note"]=> string(6) "loaded" } array(3) { ["Make"]=> string(5) "Chevy" ["Model"]=> string(4) "2500" ["Note"]=> string(0) "" } array(3) { ["Make"]=> string(5) "Chevy" ["Model"]=> string(0) "" ["Note"]=> string(6) "loaded" } 

CSVFile определяется следующим образом:

 class CSVFile extends SplFileObject { private $keys; public function __construct($file) { parent::__construct($file); $this->setFlags(SplFileObject::READ_CSV); } public function rewind() { parent::rewind(); $this->keys = parent::current(); parent::next(); } public function current() { return array_combine($this->keys, parent::current()); } public function getKeys() { return $this->keys; } } 

Если вы сделаете это так, детали будут хорошо инкапсулированы. Кроме того, в функции current() проще справляться с ошибками (например, подсчет счетчика), поэтому код, который использует данные, не нуждается в этом.

Редактировать:

Однако приведенный пример является коротким с точки зрения re-usablity. Вместо расширения от SplFileObject гораздо лучше его агрегировать:

 class KeyedArrayIterator extends IteratorIterator { private $keys; public function rewind() { parent::rewind(); $this->keys = parent::current(); parent::next(); } public function current() { return array_combine($this->keys, parent::current()); } public function getKeys() { return $this->keys; } } 

Код идентичен, но детали, которые были инкапсулированы в конструкторе, не учитываются. Это сокращение позволяет использовать тип более широко, например, с (но не только) упомянутым SplFileObject :

 $file = new SplFileObject('../data/test.csv'); $file->setFlags($file::READ_CSV); $csv = new KeyedArrayIterator($file); foreach ($csv as $line) { var_dump($line); } 

Если это сейчас звучит слишком многословно, его снова можно обернуть, чтобы снова получить более приятный фасад:

 class CSVFile extends KeyedArrayIterator { /** * @param string $file */ public function __construct($file) { parent::__construct(new SplFileObject($file)); $this->setFlags(SplFileObject::READ_CSV); } } 

Благодаря стандартной способности декорирования TraversableIterator исходный код конструктора из первого примера CSVFile можно просто скопировать на 100%.

Это последнее дополнение также позволяет сохранить исходный код, в котором используется CSVFile Iterator:

 $csv = new CSVFile('../data/test.csv'); foreach ($csv as $line) { var_dump($line); } 

Так что просто быстрый рефакторинг, позволяющий больше повторного использования кода. Вы получаете KeyedArrayIterator бесплатно.

 $csv_data = array_map('str_getcsv', file('Book.csv'));// reads the csv file in php array $csv_header = $csv_data[0];//creates a copy of csv header array unset($csv_data[0]);//removes the header from $csv_data since no longer needed foreach($csv_data as $row){ $row = array_combine($csv_header, $row);// adds header to each row as key var_dump($row);//do something here with each row } 
 function processCsv($absolutePath) { $csv = array_map('str_getcsv', file($absolutePath)); $headers = $csv[0]; unset($csv[0]); $rowsWithKeys = []; foreach ($csv as $row) { $newRow = []; foreach ($headers as $k => $key) { $newRow[$key] = $row[$k]; } $rowsWithKeys[] = $newRow; } return $rowsWithKeys; } с function processCsv($absolutePath) { $csv = array_map('str_getcsv', file($absolutePath)); $headers = $csv[0]; unset($csv[0]); $rowsWithKeys = []; foreach ($csv as $row) { $newRow = []; foreach ($headers as $k => $key) { $newRow[$key] = $row[$k]; } $rowsWithKeys[] = $newRow; } return $rowsWithKeys; } 

На этом этапе я предполагаю, что вы уже решили проблему, но подумал, что я бы предложил предложенный способ обойти это, возможно, не лучшее / самое элегантное решение, но это делает трюк:

 $row = 1; $array = array(); $marray = array(); $handle = fopen('file.csv', 'r'); if ($handle !== FALSE) { while (($data = fgetcsv($handle, 0, ',')) !== FALSE) { if ($row === 1) { $num = count($data); for ($i = 0; $i < $num; $i++) { array_push($array, $data[$i]); } } else { $c = 0; foreach ($array as $key) { $marray[$row - 1][$key] = $data[$c]; $c++; } } $row++; } echo '<pre>'; print_r($marray); echo '</pre>'; } 

Попробуйте с помощью этого кода:

 $query = "SELECT * FROM datashep_AMS.COMPLETE_APPLICATIONS"; $export= mysql_query($query); $first = true; $temp = $export[0]; //echo "<pre>"; print_r($first); exit; header('Content-Type: text/csv'); header('Content-Disposition: attachment; filename=file.csv'); header('Pragma: no-cache'); header("Expires: 0"); $outstream = fopen("php://output", "w"); foreach($export as $result) { if($first){ $titles = array(); foreach($temp as $key=>$val){ $titles[] = $key; } //print_r ($titles);exit; fputcsv($outstream, $titles); } $first = false; fputcsv($outstream, $result); } fclose($outstream); 

благодаря

Попробуй это

 $csv = array_map("str_getcsv", file('file.csv', FILE_SKIP_EMPTY_LINES)); $header = array_shift($csv); // get header from array foreach ($csv as $key => $value) { $csv[$key] = array_combine($header, $value); var_dump($csv[$key]['Model']); } var_dump($csv); 

В ответе Тима Купера выше, вместо

 $all_rows = array(); $header = null; while ($row = fgetcsv($file)) { if ($header === null) { $header = $row; continue; } $all_rows[] = array_combine($header, $row); } 

Я бы запрограммировал более элегантный и эффективный способ:

 $all_rows = array(); $header = fgetcsv($file); while ($row = fgetcsv($file)) { $all_rows[] = array_combine($header, $row); }