Question

OK, so I have the following code that reads a csv file that than outputs the result in the form of a HTML table:

$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!!! This account is mine now!!!

The contents of ac.csv are:

a, 5,
b, 10,
c, 24,
d, 21

The contents of rc.csv are:

not, 1.87,
notatall, 1.78

As you can guess from the original code, in the second to columns I need a multiplication. So for example in the second row, third coloumn I need 5*1.87 and 5*1.78. So basically a*not and a*notatall.

My code is not very efficient, how can I make it more efficient? I want all of these (somehow) put into a loop. It needs to have the exact same outcome, due to the complexity and the fact that it has 2d arrays, I have not yet been able to do this!

Was it helpful?

Solution

My only suggestion would be this one

<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>

This should not optimize in speed but it should save some memory for bigger ac.csv files, because you do not need to create a big array. But i do not think you could optimize speed here. I hope someone can provide a better answer.

EDIT #01 Here is little more flexible loop

<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>

With this one your rc.csv can store more than 2 Values to multiply. Not an speed or memory optimization but you will save code and time if you try to scale your functions/loops.

EDIT #02 I tried scrowler's approach and would suggest this one because of the logic/mark-up separation. The side effects are more use of Memory and a slightly slower script speed but it isn't significant (the speed).

Hope this will help

OTHER TIPS

<?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>

NOTE: I'm supposing $at (ac.csv) and $at2 (rc.csv) have the same lenght.

OK, I'm going to start with some concepts I think are quite important to bring up.

Firstly, you need to get your CSV files into a structured data format of some sort (an array of split values will do for CSV). I'm going to use PHP's str_getcsv() for this. This function should be called inside a loop as it takes in a string and splits it up for you into an array.

Secondly, I have a strong belief that you should do all the logic work before you go to output your data. This way your output code is kept clean and easy on the eye (yours or somebody elses). So I'm going to do the logic before the output and just use a simple output array.

So I start by recreating your CSV files in arrays:

$csv_file_1 = array(
    'a, 5,',
    'b, 10,',
    'c, 24,',
    'd, 21'
);

$csv_file_2 = array(
    'not, 1.87,',
    'notatall, 1.78'
);

In your case, you want to read CSV files into arrays, and I'd suggest the best way to do it would be to use PHP's file() function. Easy as:

// read csv files into arrays
$csv_file_1 = file('your_first.csv');
$csv_file_2 = file('your_second.csv');

Next, I want to loop through the first array, grab the two variables out of it, then loop through the second array inside that and do the calculations on the second original variable (we'll call the originals var1 and var2, and the second array factor_name and 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);
}

Now, you have an array that looks like this:

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
        )

)

This is good for you, because you now have structured data with the results you want to output, and you have all the freedom in the world for what to do with that data. I'm going to output it the same way you have in your question. The foreach loop over your array will output the title rows only, then the second time you'll output the data rows.

<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>

Now, you've asked about efficiency. When dealing with CSV files being parsed by PHP into memory (arrays), there is always the possibility that your CSV could be large, and could chew up your server's memory pretty quickly (possibly causing it to crash, restart etc in extreme cases). You probably won't encounter this in your situation, but I don't know your situation. So it's always a good idea to unset variables when you're finished with them.

unset($output, $line, $csv_file1, csv_file2);

Here's a demo of this example.

Documentation

Further reading

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top