我有一个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"
];
我不确定除了静态之外该怎么做 - 问题是带有相关数据的列可能会从一个文件更改为下一个...重新排列,删除或添加的列。
非常感谢您的想法。
答案 0 :(得分:46)
$all_rows = array();
$header = fgetcsv($file);
while ($row = fgetcsv($file)) {
$all_rows[] = array_combine($header, $row);
}
print_r($all_rows);
答案 1 :(得分:32)
PHP在SplFileObject
中提供了99.9%的所需内容,您可以通过扩展来添加缺少的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()
函数内的错误(例如计数不匹配),因此使用数据的代码不需要处理它。
<强> 编辑: 强>
然而,给出的例子在重新使用方面很短。而不是从 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%复制。
最后一次添加还可以保持使用 CSV文件迭代器的原始代码保持不变:
$csv = new CSVFile('../data/test.csv');
foreach ($csv as $line) {
var_dump($line);
}
因此,只需快速重构即可实现更多的代码重用。您可以免费获得 KeyedArrayIterator 。
答案 2 :(得分:4)
$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
}
答案 3 :(得分:2)
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;
}
答案 4 :(得分:1)
此时我假设你已经解决了这个问题,但我认为我会提出一个建议的解决方法,可能不是最好/最优雅的解决方案,但它可以解决问题:
$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>';
}
答案 5 :(得分:0)
尝试使用此代码:
$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);
由于
答案 6 :(得分:0)
试试这个
$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);
答案 7 :(得分:0)
在上面的Tim Cooper的回答中,而不是
$(function() {
$('.dropdown').each(function() {
var val = '';
var $dropdown = $(this);
var $list = $dropdown.find('ul');
$dropdown.on('show.bs.dropdown', function() {
$(document.body).on('keyup', typing);
$list.find('a').css({ background: 'transparent' });
});
$dropdown.on('hide.bs.dropdown', function() {
$(document.body).off('keyup', typing);
val = '';
$list.find('a').css({ background: 'transparent' });
});
function typing(e, alreadyChecked) { // we use alreadyChecked to break out of typing
$list.find('a').css({ background: 'transparent' });
if (e.keyCode === 8 && val.length > 1) { // This part allows backspace to delete previous characters entered
val = val.split('').splice(0, val.length - 1).join('');
} else if (e.key && e.key.length === 1) { // e.key.length === 1 this was adeed because of buttons like tab,alt,backspace etc. because they create infinite loop and exceed threads
val += e.key.toLowerCase();
} else {
return;
}
console.log(e);
if (val.length === 0) {
return;
}
var els = $list.find('a').get().filter(function(node) {
return $(node).text().toLowerCase().indexOf(val) === 0;
});
if (!els || els.length === 0) {
val = '';
if (alreadyChecked) {
typing(e, true);
}
return;
}
var scrollTop = $list[0].scrollTop;
$list[0].scrollTop = scrollTop + $(els[0]).position().top - $(els[0]).height();
$(els).css({ background: 'rgba(255, 171, 0, 0.3)' });
}
});
});
我会以更优雅高效的方式编码:
$all_rows = array();
$header = null;
while ($row = fgetcsv($file)) {
if ($header === null) {
$header = $row;
continue;
}
$all_rows[] = array_combine($header, $row);
}
答案 8 :(得分:0)
array_combine()函数仅在标题列与数据列匹配时才起作用,否则会引发错误。