Как я могу сделать это 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);

Вот демонстрация этого примера.

Документация

дальнейшее чтение

Другие вопросы по тегам