2012-04-27 75 views
1

假設一個帶有標題行的製表符分隔值文件,如何創建一個PHP數組,其頭部字段作爲鍵和數據字段作爲數據?有沒有比從TSV數據創建PHP數組更好的方法?

假設$ txtArray包含文件中的所有行,

$hdrArray = explode("\t", $txtArray[0]); 
    $i = 0; 
    foreach ($hdrArray as $hdr) { 
     $heads[$hdr] = ''; 
     $headerNames[$i++] = $hdr; 
    } 
    for ($i = 1; $i < (count($txtArray) - 1); $i++) { 
     $datArray = explode("\t", $txtArray[$i]); 
     if (count($datArray) > 1) { 
      for($j = 0; $j < count($datArray); $j++) { 
       $heads[$headerNames[$j]] = $datArray[$j];  
      } 
     } 
     # process the line 
    } 

我有含FIELD_NAME => field_data在文件的每一行中的所有字段$頭。有沒有更好的方法來編碼?

+2

你的代碼並不真正起作用,你可以包含你正在解析的文件的樣本嗎?由於這是一個技術問題,它更適合堆棧溢出,除非我錯過了某些東西? – yannis 2012-04-27 08:02:25

回答

1

什麼資格爲「更好」?

您可以使用正則表達式分割使其更健壯,但如果您可以控制源CSV,則不必擔心臟數據。

我看到的一個明顯的優化是緩存count()結果。

用途:

for ($i = 1, $c=count($txtArray); $i < c - 1); $i++) 

相反的:

for ($i = 1; $i < (count($txtArray) - 1); $i++) 

每次調用計數時間()這是重新計算的結果。做一次計算應該足夠了,所以你只需保存結果即可。

我不明白爲什麼你需要:

if (count($datArray) > 1) 

如果您正在使用「乾淨」的數據時,它應該有一個固定的數值,每行,以便對其計數檢查沒有是不必要的。爲了加快速度,您可以通過計算標題中的行數來緩存行長。

後:

$hdrArray = explode("\t", $txtArray[0]); 

務必:

$c2 = count($hdrArray); 

然後用它在第二個for循環:

for($j = 0; $j < c2; $j++) 

如果你不得不擔心空行,它可能會更快地搜索一個空行並在循環中跳過它。

像這樣:

// skip the row if the $datArray contains an empty array 
if($datArray == array()) { 
    continue; 
} 
$heads[$headerNames[$j]] = $datArray[$j];  

總之你:

$hdrArray = explode("\t", $txtArray[0]); 
$c2 = count($hdrArray); 

// it has an iterator variable... 
// I don't understand why you wouldn't use a for loop here 
$i = 0; 
foreach ($hdrArray as $hdr) { 
    $heads[$hdr] = ''; 
    $headerNames[$i++] = $hdr; 
} 

for ($i = 1, $c=count($txtArray); $i < c1 - 1); $i++) { 
    $datArray = explode("\t", $txtArray[$i]); 
    for($j = 0; $j < c2; $j++) 
     // skip the row if the $datArray contains an empty array 
     if($datArray == array()) { 
      continue; 
     } 
     $heads[$headerNames[$j]] = $datArray[$j]; 
    }  
} 

我假設你的第一個執行工作,以及源數據實際上是CSV(即固定數量的行/列

我所做的只是應用一些簡單的(和普通的)優化以減少不必要的計算次數。漂亮的基本東西,你習慣看後不久。

1

假設你的輸入文件是這樣的:

head1 head2 head3 
v11 v12 v13 
v21 v22 v23 
v31 v32 v33 

更簡單的方法來解析這將是:

$hdrArray = explode("\t", $txtArray[0]); 
// array(3) { [0]=> string(5) "head1" [1]=> string(5) "head2" [2]=> string(6) "head3 " } 

$length = count($txtArray) - 1; // having count in the for loop means it'll be executed at each iteration 
$data = array(); 

for($i = 1; $i <= $length; $i++) { 
    $datArray = explode("\t", $txtArray[$i]); 
    // array(3) { [0]=> string(3) "v11" [1]=> string(3) "v12" [2]=> string(4) "v13 " } 

    foreach($hdrArray as $key => $header) { 
     $data[$i - 1][$header] = $datArray[$key]; // $i - 1 to start your $data array from 0 
    } 
} 

和你$data陣列看起來像:

array(3) { 
    [0]=> 
    array(3) { 
    ["head1"]=> 
    string(3) "v11" 
    ["head2"]=> 
    string(3) "v12" 
    ["head3"]=> 
    string(4) "v13" 
    } 
    [1]=> 
    array(3) { 
    ["head1"]=> 
    string(3) "v21" 
    ["head2"]=> 
    string(3) "v22" 
    ["head3"]=> 
    string(4) "v23" 
    } 
    [2]=> 
    array(3) { 
    ["head1"]=> 
    string(3) "v31" 
    ["head2"]=> 
    string(3) "v32" 
    ["head3"]=> 
    string(3) "v33" 
    } 
} 

您可以完全跳過count,但需要額外的迭代:

foreach($txtArray as $i => $value) { 
    if($i == 0) continue; // header, move on 

    $datArray = explode("\t", $value); 

    foreach($hdrArray as $key => $header) { 
     $data[$i - 1][$header] = $datArray[$key]; 
    } 
} 

這實際上可能是一點點比使用計數,作爲第一次迭代立即停止,並繼續循環到下一個速度更快。但是這取決於你陣列的大小,收益/損失可能是微不足道的。

相關問題