2011-12-02 19 views
19

多維數組我有CSV值是這樣的:str_getcsv到PHP

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

我要帶一個完整的CSV字符串,並讀入一期多維數組,這樣我得到:

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

我想要這樣的輸出,請注意CSV值是動態的。

+0

CSV數據的最後一行是否應該有另一個逗號?如果行不全部具有相同數量的列,則看起來不像有效的CSV數據。還是代碼需要考慮不同數量的列? – Wiseguy

+0

它的樣子,第一行將是一個數組的鍵,然後其他值是它的值。 'thing'=>''部分的 ,這是正確的。 – PinoyStackOverflower

+0

我明白了,但CSV數據的最後一行是'have,fun',它只有兩列,而不是其他行。我們是否需要考慮那些列數錯誤的行? – Wiseguy

回答

33

假設在CSV數據每行具有相同的列數,這應該工作。

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

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

如果線路具有可變數目的列(如在例如,在最後一行具有兩列,而不是3),使用這個循環來代替:

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

那麼在單個字段中包含\ n的csv數據呢? csv中的通常表示法是用引號括住這些字段,例如, 「在一個領域有一定的價值」。所以,解析時必須忽略這些\ n。你的爆炸方法會將它們關閉。 –

+0

@ChrisPillen雖然不是提問者的要求之一,但這是一個有效的觀點。你認爲最好的補救措施是什麼?將CSV數據保存到['tmpfile()'](http://php.net/tmpfile)並使用['fgetcsv()'](http://php.net/fgetcsv)解析出來?我應該在我的答案中添加一個例子嗎? – Wiseguy

+0

@Wiseguy你可以使用正則表達式來解析數據,但使用臨時文件和'fgetcsv()'會更簡單,更乾淨。 –

4

這裏是一個完整的解決方案:

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

那麼,我們在這裏幹什麼?

  • 首先,你的CSV數據被分成行的陣列explode
  • 由於在CSV第一行描述的數據格式,它必須從實際的數據行(explodeunset
  • 分離爲了存儲的結果,我們初始化
  • FOREACH用於通過由線的數據線,以迭代的新陣列($results)。對於每個行:
    • 行被解析PHP的str_getcsv
    • 空結果陣列被初始化
    • 每行的格式的光檢查。單元格被添加並且缺少的列用空字符串填充。
+0

這是不正確的輸出,我希望,謝謝\爲您的答案:) – PinoyStackOverflower

+0

這是更復雜的問題,我想。檢查修改後的答案。接下來會詳細解釋。 – jsalonen

+0

添加說明。鑑於你的描述,這應該回答這個問題。 – jsalonen

2

這裏是一個非常乾淨和簡單的解決方案:

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