假设带有标题行的制表符分隔值文件,如何创建一个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
}
我有$ head包含field_name =&gt; field_data表示文件每行中的所有字段。有没有更好的方法来编码?
答案 0 :(得分:1)
什么符合“更好”的条件?
您可以使用正则表达式拆分使其更加健壮,但如果您可以控制源CSV,则不必担心脏数据。
我看到的一个明显的优化是缓存count()结果。
使用:强>
for ($i = 1, $c=count($txtArray); $i < c - 1); $i++)
代替:
for ($i = 1; $i < (count($txtArray) - 1); $i++ )
每次调用count()时,都会重新计算结果。进行一次计算就足够了,所以你只需保存结果。
我不明白你为什么需要:
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 :(得分: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];
}
}
这实际上可能比使用count更快,因为第一次迭代立即停止,循环继续到下一次。但它实际上取决于阵列的大小,并且增益/损失可能是微不足道的。