2011-12-02 16 views
19

ho valori CSV come questo:str_getcsv in un array multidimensionale in php

$csv_data = "test,this,thing 
      hi,there,this 
      is,cool,dude 
      have,fun"; 

voglio prendere un'intera stringa CSV e leggerlo in un array multidemensional in modo che ottengo:

array(
    array(
     'test' => 'hi', 
     'this' => 'there', 
     'thing' => 'this' 
    ), 
    array(
     'test' => 'is', 
     'this' => 'cool', 
     'thing' => 'dude' 
    ), 
    array(
     'test' => 'have', 
     'this' => 'fun', 
     'thing' => '' 
    ) 
); 

Voglio un'uscita del genere, prendi nota che il valore CSV è dinamico.

+0

Se l'ultima riga dei dati CSV ha un'altra virgola? Non sembrano dati CSV validi se le righe non hanno tutti lo stesso numero di colonne. O il codice deve tenere conto di quel numero variabile di colonne? – Wiseguy

+0

è come, la prima riga sarebbe la chiave di una matrice, quindi altri sono il suo valore. sulla parte 'cosa' => '', che è corretta. – PinoyStackOverflower

+0

L'ho capito, ma l'ultima riga di dati CSV è 'have, fun', che ha solo due colonne, non tre come le altre righe. Dobbiamo considerare le righe con il numero sbagliato di colonne del genere? – Wiseguy

risposta

33

Supponendo ogni riga nei dati CSV ha lo stesso numero di colonne, questo dovrebbe funzionare.

$lines = explode("\n", $csv_data); 
$head = str_getcsv(array_shift($lines)); 

$array = array(); 
foreach ($lines as $line) { 
    $array[] = array_combine($head, str_getcsv($line)); 
} 

Se linee hanno un numero variabile di colonne (come nel tuo esempio, dove l'ultima riga ha 2 colonne invece di 3), utilizzare questa sequenza invece:

foreach ($lines as $line) { 
    $row = array_pad(str_getcsv($line), count($head), ''); 
    $array[] = array_combine($head, $row); 
} 
+1

E i dati CSV che contengono \ n in singoli campi. La solita notazione in csv consiste nel racchiudere tali campi tra virgolette, ad es. "qualche valore \ nin un campo". Quindi, quelli \ n devono essere ignorati durante l'analisi. Il tuo approccio esplosivo li taglierà. –

+0

@ChrisPillen Sebbene non sia uno dei requisiti del richiedente, questo è un punto valido. Quale pensi che il miglior rimedio sarebbe? Salva i dati CSV in un ['tmpfile()'] (http://php.net/tmpfile) e analizzali usando ['fgetcsv()'] (http://php.net/fgetcsv)? Dovrei aggiungere un esempio di questo alla mia risposta? – Wiseguy

+0

@Wiseguy È possibile utilizzare regex per analizzare i dati, ma l'utilizzo di un file temporaneo e 'fgetcsv()' sarebbe il più semplice e molto più pulito. –

4

Ecco una soluzione completa:

$lines = explode("\n", $csv_data); 
$formatting = explode(",", $lines[0]); 
unset($lines[0]); 
$results = array(); 
foreach ($lines as $line) { 
    $parsedLine = str_getcsv($line, ','); 
    $result = array(); 
    foreach ($formatting as $index => $caption) { 
     if(isset($parsedLine[$index])) { 
     $result[$formatting[$index]] = trim($parsedLine[$index]); 
     } else { 
     $result[$formatting[$index]] = ''; 
     } 
    } 
    $results[] = $result; 
} 

Allora, cosa ci facciamo qui?

  • Innanzitutto, i dati CSV viene suddiviso in una matrice di righe con explode
  • Poiché la prima riga del CSV descrive formato di dati, deve essere separato dalle righe di dati effettivi (explode e unset)
  • Per memorizzare i risultati, inizializziamo un nuovo array ($results)
  • Foreach viene utilizzato per scorrere i dati riga per riga. Per ogni linea:
    • linea viene analizzato con str_getcsv
    • Un array di risultati vuoto PHP viene inizializzato
    • Ogni linea è controllato in funzione del formato. Le celle vengono aggiunte e le colonne mancanti vengono riempite con stringhe vuote.
+0

Non si sta emettendo correttamente quello che desideravo, grazie per la risposta :) – PinoyStackOverflower

+0

Era un problema molto più complesso che pensavo. Controlla la risposta rivista. Seguirà una spiegazione dettagliata. – jsalonen

+0

Spiegazione aggiunta. Data la tua descrizione questo dovrebbe rispondere alla domanda. – jsalonen

2

Ecco una soluzione molto semplice e pulita:

function parse_row($row) { 
    return array_map('trim', explode(',', $row)); 
} 

$rows = str_getcsv($csv_data, "\n"); 
$keys = parse_row(array_shift($rows)); 
$result = array(); 

foreach ($rows as $row) { 
    $row = parse_row($row); 
    $row = array_pad($row, 3, NULL); 

    $result[] = array_combine($keys, $row); 
} 
Problemi correlati