CSV в ассоциативный массив
Я видел множество примеров того, как взять CSV-файл, а затем создать ассоциативный массив с заголовками в качестве ключей.
например:
Brand,Model,Part,Test
Honda,Civic,123,244
Honda,Civic,135,434
Toyota,Supra,511,664
где он создаст массив, такой как Array[$num][$key]
здесь $key
было бы тавром, моделью, частью, испытанием.
поэтому, если бы я хотел получить доступ к тестовому значению "434", мне пришлось бы зацикливать каждый индекс в массиве, а затем игнорировать любые бренды, которые не были honda, и любые модели, которые не были Гражданский
что мне нужно сделать, это получить доступ к значению наиболее непосредственно, а не через цикл for, проходящий через каждый индекс $num. Я хочу иметь доступ к тесту значений " 434 " с помощью:
Array['Honda']['Civic']['135']
или контролировать заявление с петлей через каждую модель Honda имеет... что-то вроде
foreach $model in Array['Honda']
по крайней мере, мне нужно иметь возможность пройти через каждую модель с учетом известного бренда и получить доступ ко всей относительной информации для каждого.
Edit:
просто чтобы подтвердить, что я настраивал этот пример. Мои фактические данные имеют заголовки, такие как:
brand model part price shipping description footnote
из которых мне нужно получить доступ ко всей информации, связанной с частью (цена, доставка,desc, сноска)
5 ответов
запустите файл csv строка за строкой и вставьте в массив, например:
$array = $fields = array(); $i = 0;
$handle = @fopen("file.csv", "r");
if ($handle) {
while (($row = fgetcsv($handle, 4096)) !== false) {
if (empty($fields)) {
$fields = $row;
continue;
}
foreach ($row as $k=>$value) {
$array[$i][$fields[$k]] = $value;
}
$i++;
}
if (!feof($handle)) {
echo "Error: unexpected fgets() fail\n";
}
fclose($handle);
}
слишком много решений. Я всегда считал это самым простым:
<?php
/* Map Rows and Loop Through Them */
$rows = array_map('str_getcsv', file('file.csv'));
$header = array_shift($rows);
$csv = array();
foreach($rows as $row) {
$csv[] = array_combine($header, $row);
}
?>
для создания ассоциативного массива списка используйте что-то вроде:
$keys = fgetcsv($f);
while (!feof($f)) {
$array[] = array_combine($keys, fgetcsv($f));
}
и для обхода и фильтрации по определенным атрибутам напишите функцию, например:
function find($find) {
foreach ($array as $row) {
if (array_intersect_assoc($row, $find) == $find) {
$result[] = $row;
}
}
}
где вы бы вызвать его с $find = array(Brand=>Honda, Model=>Civic, Part=>135)
отфильтровать искомые модели. Другая структура позиционного массива кажется не очень работоспособной, если вы не хотите получить доступ только к атрибуту "Test".
попробуйте этот простой алгоритм:
$assocData = array();
if( ($handle = fopen( $importedCSVFile, "r")) !== FALSE) {
$rowCounter = 0;
while (($rowData = fgetcsv($handle, 0, ",")) !== FALSE) {
if( 0 === $rowCounter) {
$headerRecord = $rowData;
} else {
foreach( $rowData as $key => $value) {
$assocData[ $rowCounter - 1][ $headerRecord[ $key] ] = $value;
}
}
$rowCounter++;
}
fclose($handle);
}
var_dump( $assocData);
вот решения, которые будут работать, указав локальный файл или URL-адрес. Вы также можете включать и выключать ассоциацию. Надеюсь, это поможет.
class CSVData{
public $file;
public $data;
public $fp;
public $caption=true;
public function CSVData($file=''){
if ($file!='') getData($file);
}
function getData($file){
if (strpos($file, 'tp://')!==false){
copy ($file, '/tmp/csvdata.csv');
if ($this->fp=fopen('/tmp/csvdata.csv', 'r')!==FALSE){
$this->readCSV();
unlink('tmp/csvdata.csv');
}
} else {
$this->fp=fopen($file, 'r');
$this->readCSV();
}
fclose($this->fp);
}
private function readCSV(){
if ($this->caption==true){
if (($captions=fgetcsv($this->fp, 1000, ","))==false) return false;
}
$row=0;
while (($data = fgetcsv($this->fp, 1000, ",")) !== FALSE) {
for ($c=0; $c < count($data); $c++) {
$this->data[$row][$c]=$data[$c];
if ($this->caption==true){
$this->data[$row][$captions[$c]]=$data[$c];
}
}
$row++;
}
}
}
попробуйте это использование:
$o=new CSVData();
$o->getData('/home/site/datafile.csv');
$data=$o->data;
print_r($data);