2011-01-26 11 views
26

Widziałem wiele przykładów, jak pobrać plik CSV, a następnie utworzyć asocjacyjną tablicę z nagłówkami jako kluczami.CSV do asocjacyjnej tablicy

Na przykład:

Brand,Model,Part,Test 
Honda,Civic,123,244 
Honda,Civic,135,434 
Toyota,Supra,511,664 

Gdzie byłoby utworzyć tablicę takich jak Array[$num][$key] gdzie $key byłoby marka, model, Part, test.

Więc Gdybym chciał uzyskać dostęp do wartości testowej „434” Musiałbym pętli każdy indeks w tablicy, a następnie ignorować żadnych marek, które nie były Hondy, oraz wszelkie modele, które nie były Civic


To, co muszę zrobić, to uzyskać dostęp do wartości najbardziej bezpośrednio, zamiast przechodzić przez pętlę for przechodzącą przez każdy indeks $ num. Chcę być w stanie uzyskać dostęp do testu wartość „434” z:

Array['Honda']['Civic']['135']

lub kontrolować instrukcji for z pętli przez każdego modelu Honda ... coś jak

foreach $model in Array['Honda']

Przynajmniej muszę być w stanie przejść przez każdy model ze znaną marką i uzyskać dostęp do wszystkich względnych informacji dla każdego.

Edytuj:

Tylko dla potwierdzenia, że ​​ustawiłem ten przykład. My rzeczywiście danych ma nagłówki typu:

brand model part price shipping description footnote

o której trzeba uzyskać dostęp do wszystkich informacji przywiązane do części (cena, wysyłka, desc przypis)

+1

[Przykład (y), jak to zrobić za pomocą 'SplFileInfo'] (http://stackoverflow.com/a/10181302/367456) – hakre

Odpowiedz

48

przejechany linii pliku CSV przez linię i włóż do tablicy jak:

$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); 
} 
+0

pracuje dla przykład OP dał, ale uważaj, że pliki csv mogą mieć przecinki w polach tekstowych jak: field1, "field two", "field, 3", field4. – xelco52

+1

@ xelco52: 'fgetcsv()' poradzi sobie z tym dobrze. – BoltClock

+0

masz prawo zmienić na fgetcsv –

15

aby utworzyć tablicę asocjacyjną lista używać coś takiego:

$keys = fgetcsv($f); 
while (!feof($f)) { 
    $array[] = array_combine($keys, fgetcsv($f)); 
} 

I przechodzić przez filtr i specyficznych cech napisać funkcję jak:

function find($find) { 
    foreach ($array as $row) { 
     if (array_intersect_assoc($row, $find) == $find) { 
      $result[] = $row; 
     } 
    } 
} 

Gdzie byś powoływania go $find = array(Brand=>Honda, Model=>Civic, Part=>135) odfiltrować poszukiwane modele. Druga pozycyjna struktura tablicowa wydaje się mało funkcjonalna, chyba że chcesz tylko uzyskać dostęp do atrybutu "Test".

2

Oto rozwiązania, które działają, określając lokalny plik lub adres URL. Możesz także włączać i wyłączać powiązanie. Mam nadzieję, że to pomaga.

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++; 
     } 
    } 
} 

Spróbuj użycia:

$o=new CSVData(); 
$o->getData('/home/site/datafile.csv'); 
$data=$o->data; 
print_r($data); 
+0

blog link jest martwy –

4

Spróbuj prosty algorytm:

 $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); 
23

Zbyt wiele długich rozwiązań.Zawsze uważałem, że jest to najprostsza:

<?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); 
    } 
?> 
+0

Prosty i dynamiczny - świetne rozwiązanie. Dzięki! – domdambrogia

+0

Dzięki, stary, świetne rozwiązanie. – GuRu

+0

To działało świetnie, nigdy nie korzystałem z kombinacji tablic, ale działało to świetnie! Dziękuję Ci! –

Powiązane problemy