2012-04-16 7 views
15

Mam plik CSV z pierwszym wierszem zawierającym nazwy pól. Przykładem danych jest ...Proces CSV w tablicę z nagłówkami kolumn dla klucza

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

Potrzebuję moich danych sformatowanych w tablicy par klucz-wartość, gdzie nazwa klucza jest nagłówkiem kolumny. Myślę, że to będzie coś takiego dla rzędu 1:

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

... Row 2 ...

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

... i wiersz 3 ...

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

I "Nie jestem pewien, jak to zrobić inaczej niż statycznie - problem polega na tym, że kolumny z powiązanymi danymi mogą się zmieniać z jednego pliku na następny ... kolumny uporządkowane, upuszczone lub dodane.

Pomysły są mile widziane.

+0

zapewne na myśli 2500 w drugim przykładzie tablicy – user1899415

Odpowiedz

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

Dziękujemy za szybką odpowiedź. Jest blisko, chociaż kończę danymi w kluczach. Nie widać żadnych nagłówków kolumn w żadnej z zwróconych tablic. –

+1

@BitBucket: Jeśli zrobisz zrzut danych w '$ all_rows', powinieneś zobaczyć tablicę z pod-tablicami, które mają dane nagłówka jako klucze. –

+0

Pamiętaj, że musisz uruchomić nagłówek $, kiedy go utworzysz, aby upewnić się, że podajesz kolumny bez tytułów, np. "Nieznany". $ x lub kombinacja macierzy będą różne długości – Titan

27

PHP oferuje już 99,9%, co jest potrzebne w ciągu SplFileObject, dodać brakujące 0,1% rozciągający się od niego. W poniższym przykładzie CSVFile rozciąga się z niego:

$csv = new CSVFile('../data/test.csv'); 

foreach ($csv as $line) 
{ 
    var_dump($line); 
} 

Z Twojego przykład danych:

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 jest zdefiniowana jako następujące:

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

Jeśli zrobisz to w ten sposób, tym szczegóły są ładnie zamknięte. Ponadto łatwiej jest radzić sobie z błędami (np. Z niezgodnością liczników) wewnątrz funkcji current(), więc kod, który wykorzystuje dane, nie musi się z nimi obchodzić.

Edit:

Jednak Przykład podany jest krótki w zakresie ponownego użyteczność swoich. Zamiast rozciągający się od SplFileObject to o wiele lepiej, aby je zsumować:

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

Kod jest identyczne ale szczegóły, które zostały zamknięte w konstruktorze są opuszczone. Ta redukcja pozwala na szersze wykorzystanie tego typu, np.z (ale nie tylko) wspomniany SplFileObject:

$file = new SplFileObject('../data/test.csv'); 
$file->setFlags($file::READ_CSV); 

$csv = new KeyedArrayIterator($file); 

foreach ($csv as $line) { 
    var_dump($line); 
} 

Jeśli to teraz brzmi zbyt rozwlekły, że znowu może być owinięty dać go ponownie ładniejszy elewacji:

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

Dzięki Standardowa zdolność do dekorowania: TraversableIterator, oryginalny kod konstruktora z pierwszego przykładu CSVFile może być skopiowany w 100%.

Ten ostatni dodatek pozwala również zachować oryginalny kod wykorzystuje się CSVFile Iterator nienaruszone:

$csv = new CSVFile('../data/test.csv'); 

foreach ($csv as $line) { 
    var_dump($line); 
} 

więc tylko szybkie refaktoryzacji w celu umożliwienia więcej kodu-ponownego użycia. Dostajesz KeyedArrayIterator za darmo.

+1

bardzo ładne ...... –

+0

Czy mógłbyś myśleć zręcznie, w jaki sposób radzić sobie z nagłówkowymi plikami CSV w interesie? –

+1

To całkiem proste: Zostaw zamiast tego funkcję 'rewind' i przekazuj klucze w konstruktorze. Jeśli potrzebujesz większej elastyczności, dodałem trochę kodu do przykładów, ale wciąż jest to całkiem alfa: https://gist.github.com/4153380 – hakre

0

spróbować z tym kodem:

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

Dzięki

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

W tym momencie jestem przy założeniu, że już rozwiązany problem, ale myślałem, że będę rzucać w sugerowanej sposób wokół tego , prawdopodobnie nie jest to najlepsze/najbardziej eleganckie rozwiązanie, ale to wystarczy:

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

Spróbuj

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

odpowiedź Tim Cooper powyżej, zamiast

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

bym kodu w bardziej elegancki i skuteczny sposób:

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