Как я могу сделать это CSV чтения PHP-кода более эффективным
Итак, у меня есть следующий код, который читает файл CSV, который затем выводит результат в виде таблицы HTML:
$fhdrop = fopen("ac.csv", "r");
while (!feof($fhdrop) ) {
$at[] = fgetcsv($fhdrop, 1024);
}
$fhdrop2 = fopen("rc.csv", "r");
while (!feof($fhdrop2) ) {
$at2[] = fgetcsv($fhdrop2, 1024);
}
?>
<table border=1>
<tr>
<td>a</td>
<td>b</td>
<td>c</td>
<td>d</td>
<tr>
<td><?php echo $at[0][0] ?></td>
<td><?php echo $at[0][1] ?></td>
<td><?php echo number_format($at[0][1]*$at2[0][1],2) ?></td>
<td><?php echo number_format($at[0][1]*$at2[1][1],2) ?></td>
</tr>
<tr>
<td><?php echo $at[1][0] ?></td>
<td><?php echo $at[1][1] ?></td>
<td><?php echo number_format($at[1][1]*$at2[0][1],2) ?></td>
<td><?php echo number_format($at[1][1]*$at2[1][1],2) ?></td>
</tr>
<tr>
<td><?php echo $at[2][0] ?></td>
<td><?php echo $at[2][1] ?></td>
<td><?php echo number_format($at[2][1]*$at2[0][1],2) ?></td>
<td><?php echo number_format($at[2][1]*$at2[1][1],2) ?></td>
</tr>
<tr>
<td><?php echo $at[3][0] ?></td>
<td><?php echo $at[3][1] ?></td>
<td><?php echo number_format($at[3][1]*$at2[0][1],2) ?></td>
<td><?php echo number_format($at[3][1]*$at2[1][1],2) ?></td>
Wag1 pplz!!! Этот аккаунт теперь мой!!!
Содержимое ac.csv:
a, 5,
b, 10,
c, 24,
d, 21
Содержимое rc.csv:
not, 1.87,
notatall, 1.78
Как вы можете догадаться из исходного кода, во втором столбце мне нужно умножение. Так, например, во втором ряду, в третьем столбце мне нужно 5*1,87 и 5*1,78. Так что, в основном, не и не все.
Мой код не очень эффективен, как я могу сделать его более эффективным? Я хочу, чтобы все это (как-то) было зациклено. У него должен быть точно такой же результат, из-за сложности и того факта, что он имеет 2d массивы, я пока не смог этого сделать!
3 ответа
Мое единственное предложение будет этим
<table>
<tr>
<td>a</td>
<td>b</td>
<td>c</td>
<td>d</td>
</tr>
<?php
$fhdrop2 = fopen("rc.csv", "r");
while (!feof($fhdrop2) ) {
$at2[] = fgetcsv($fhdrop2, 1024);
}
$fhdrop = fopen("ac.csv", "r");
while (!feof($fhdrop) ){
$at = fgetcsv($fhdrop, 1024);
?>
<tr>
<td><?php echo $at[0]; ?></td>
<td><?php echo $at[1]; ?></td>
<td><?php echo number_format($at[1]*$at2[0][1],2); ?></td>
<td><?php echo number_format($at[1]*$at2[1][1],2); ?></td>
</tr>
<?php
}
?>
</table>
Это не должно оптимизировать по скорости, но должно сэкономить некоторую память для больших файлов ac.csv, потому что вам не нужно создавать большой массив. Но я не думаю, что вы могли бы оптимизировать скорость здесь. Я надеюсь, что кто-то может дать лучший ответ.
РЕДАКТИРОВАТЬ #01 Вот немного более гибкий цикл
<tr>
<td><?php echo $at[0] ?></td>
<td><?php echo $at[1] ?></td>
<?php for($i = 0; $i < sizeof($at2); $i++){ ?>
<td><?php echo number_format($at[1]*$at2[$i][1],2) ?></td>
<?php } ?>
</tr>
С этим ваш rc.csv может хранить более 2 значений для умножения. Не оптимизация скорости или памяти, но вы сэкономите код и время, если попытаетесь масштабировать свои функции / циклы.
РЕДАКТИРОВАТЬ #02 Я попробовал подход scrowler и предложил бы этот из-за разделения логики / разметки. Побочными эффектами являются более интенсивное использование памяти и немного меньшая скорость работы скрипта, но она незначительна (скорость).
Надеюсь, это поможет
<?php
$fhdrop = fopen("ac.csv", "r");
while (!feof($fhdrop) ) {
$at[] = fgetcsv($fhdrop, 1024);
}
$fhdrop2 = fopen("rc.csv", "r");
while (!feof($fhdrop2) ) {
$at2[] = fgetcsv($fhdrop2, 1024);
}
?>
<table border=1>
<tr>
<td>a</td>
<td>b</td>
<td>c</td>
<td>d</td>
</tr>
<?php
for ($i = 0; $i < sizeof($at); $i++){
?>
<tr>
<td><?php echo $at[$i][0] ?></td>
<td><?php echo $at[$i][1] ?></td>
<td><?php echo number_format($at[$i][1]*$at2[$i][1],2) ?></td>
<td><?php echo number_format($at[$i][1]*$at2[$i][1],2) ?></td>
</tr>
<?php
}
?>
</table>
ПРИМЕЧАНИЕ: я предполагаю, что $at (ac.csv) и $at2 (rc.csv) имеют одинаковую длину.
Хорошо, я собираюсь начать с некоторых концепций, которые я считаю весьма важными.
Во-первых, вам нужно перевести ваши CSV-файлы в какой-то структурированный формат данных (для CSV подойдет массив разделенных значений). Я собираюсь использовать PHP str_getcsv()
за это. Эта функция должна вызываться внутри цикла, поскольку она принимает строку и разделяет ее для вас в массив.
Во-вторых, я твердо убежден, что вы должны выполнить всю логику работы, прежде чем приступить к выводу своих данных. Таким образом, ваш выходной код будет чистым и легким для глаз (ваш или кто-то другой). Поэтому я собираюсь сделать логику перед выводом и просто использовать простой выходной массив.
Итак, я начну с воссоздания ваших CSV-файлов в массивах:
$csv_file_1 = array(
'a, 5,',
'b, 10,',
'c, 24,',
'd, 21'
);
$csv_file_2 = array(
'not, 1.87,',
'notatall, 1.78'
);
В вашем случае вы хотите читать файлы CSV в массивы, и я бы посоветовал лучший способ сделать это - использовать PHP file()
функция. Легко как:
// read csv files into arrays
$csv_file_1 = file('your_first.csv');
$csv_file_2 = file('your_second.csv');
Затем я хочу пройтись по первому массиву, извлечь из него две переменные, затем пройти по второму массиву внутри него и выполнить вычисления для второй исходной переменной (мы назовем оригиналы var1
а также var2
и второй массив factor_name
а также factor
):
foreach($csv_file_1 as $originals) {
// get variables from each line
list($var1, $var2) = str_getcsv($originals);
// remove whitespace from second variable
$var2 = trim($var2);
$factors_output = array();
// get multiplier variables
foreach($csv_file_2 as $factors) {
list($factor_name, $factor) = str_getcsv($factors);
// do calculation, add to temporary array
$factors_output[] = $var2 * $factor;
}
// array_merge the original vars with the multiplied vars
$output[] = array_merge(array($var1, $var2), $factors_output);
}
Теперь у вас есть массив, который выглядит так:
Array
(
[0] => Array
(
[0] => a
[1] => 5
[2] => 9.35
[3] => 8.9
)
[1] => Array
(
[0] => b
[1] => 10
[2] => 18.7
[3] => 17.8
)
[2] => Array
(
[0] => c
[1] => 24
[2] => 44.88
[3] => 42.72
)
[3] => Array
(
[0] => d
[1] => 21
[2] => 39.27
[3] => 37.38
)
)
Это хорошо для вас, потому что у вас теперь есть структурированные данные с результатами, которые вы хотите вывести, и у вас есть вся свобода в мире, что делать с этими данными. Я собираюсь вывести его так же, как у вас в вопросе. Цикл foreach над вашим массивом будет выводить только строки заголовков, затем во второй раз вы будете выводить строки данных.
<table border="1">
<tr>
<? foreach($output as $line) : ?>
<td><?=$line[0]?></td>
<? endforeach; ?>
</tr>
<? foreach($output as $line) : ?>
<tr>
<? foreach($line as $var) : ?>
<td><?=$var?></td>
<? endforeach; ?>
</tr>
<? endforeach; ?>
</table>
Теперь вы спросили об эффективности. При работе с файлами CSV, анализируемыми PHP в память (массивы), всегда существует вероятность того, что CSV-файл может быть большим и достаточно быстро поглотить память вашего сервера (что может привести к его аварийному завершению, перезапуску и т. Д. В крайних случаях). Вы, вероятно, не столкнетесь с этим в вашей ситуации, но я не знаю вашу ситуацию. Так что это всегда хорошая идея unset
переменные, когда вы закончите с ними.
unset($output, $line, $csv_file1, csv_file2);
Вот демонстрация этого примера.
Документация
- http://php.net/manual/en/function.file.php
- http://php.net/manual/en/function.str-getcsv.php
- http://php.net/manual/en/control-structures.foreach.php
- http://php.net/unset
дальнейшее чтение