Home > Mobile >  Print HTML table with data from 3d associative array where amount ranges consider current value and
Print HTML table with data from 3d associative array where amount ranges consider current value and

Time:08-02

I've just begun learning php and this is my first time encountering associative arrays. I'm trying to echo a specific value from the innermost array but failing to do so.

This is my array -

define('TAX_RATES', array(
'Single' => array(
  'Rates' => array(10,12,22,24,32,35,37),
  'Ranges' => array(0,9700,39475,84200,160725,204100,510300),
  'MinTax' => array(0, 970,4543,14382,32748,46628,153798)
  ),
'Married_Jointly' => array(
  'Rates' => array(10,12,22,24,32,35,37),
  'Ranges' => array(0,19400,78950,168400,321450,408200,612350),
  'MinTax' => array(0, 1940,9086,28765,65497,93257,164709)
  ),
'Married_Separately' => array(
  'Rates' => array(10,12,22,24,32,35,37),
  'Ranges' => array(0,9700,39475,84200,160725,204100,306175),
  'MinTax' => array(0, 970,4543,14382.50,32748.50,46628.50,82354.75)
  ),
'Head_Household' => array(
  'Rates' => array(10,12,22,24,32,35,37),
  'Ranges' => array(0,13850,52850,84200,160700,204100,510300),
  'MinTax' => array(0, 1385,6065,12962,31322,45210,152380)
    )
  )
);

I have to run a foreach loop to loop through the 'Single', 'Married_Jointly' etc. statuses to output the first row and then a for loop to output the rest of the rows. The output should look like:

 Single
 Taxable Income Tax Rate
 $0 - $9700     10%
 $9701 - $39475 $970   12%
 .....

 Married_Jointly
 Taxable Income Tax Rate
 $0 - $19400    10%
 $19401 - $78950 $1940   12%
 .....

Code I've tried so far:

$keys = array_keys(TAX_RATES);

  for($i = 0; $i < count(TAX_RATES); $i  ){
    echo $keys[$i] . "<br>";
    echo "<table>";
    echo "<tr>";
    echo "<th> Taxable Income </th>";
    echo "<th> Tax Rate </th>";
    echo "</tr>";
    
    foreach(TAX_RATES[$keys[$i]] as $key => $value){
     
      echo "<tr>";
      echo "<td> $0 - $value[1] </td>";
      echo "<td> $value[0]% </td>";
      echo "</table> <br>";
    
    }
    
  }

This is the result I'm getting -

  Single
  Taxable Income    Tax Rate
   $0 - $12         10%
   $0 - $9700        0%
   ....
   Married_Jointly
   Taxable Income   Tax Rate
   $0 - $12         10%
   $0 - $19400      0%
   .....

I'm having a tough time iterating over a complex associative array like this, any help would be appreciated.

CodePudding user response:

<?php
// Loop through the different groupings, Single, Married_Jointly, etc.
foreach(TAX_RATES as $group => $info) {
    echo $group . "<br>";
    echo "<table>";
    echo "<tr>";
    echo "<th> Taxable Income </th>";
    echo "<th> Tax Rate </th>";
    echo "</tr>";

    // Loop through the rates.
    foreach ($info['Rates'] as $key => $value){
      // Get the lower bound of the range.
      $range_lower_bound = $info['Ranges'][$key];
      // If the lower bound range is not the first range,
      // then increment by 1, since the original value is
      // already used as the upper bound of the previous
      // range.
      if ($key !== 0) {
        $range_lower_bound  = 1;
      }

      // Get the upper bound, which is the next item 
      // along. Check that it exists; it won't if we are
      // on the last item.
      $range_upper_bound = $info['Ranges'][$key   1] ?? NULL;

      // Produce the range text that we will print.
      $range_text = '$' . $range_lower_bound;
      // If an upper bound exists, print it, otherwise
      // just print ' '.
      $range_text .= $range_upper_bound
        ? ' - $' . $range_upper_bound
        : ' ';

      $rate = $value . '%';

      // The minimum tax.
      $minimum_tax = $info['MinTax'][$key];
      // Prefix the rate percent with the minimum tax if
      // the minimum tax is more than 0.
      if ($minimum_tax > 0) {
        $rate = '$' . $minimum_tax . '   ' . $rate;
      }

      echo "<tr>";
      echo "<td>" . $range_text . "</td>";
      echo "<td>" . $rate . "</td>";
      echo "</tr>";
    }
    
    echo "</table>";
}

CodePudding user response:

I recommend breaking up your table generating into its repeatable parts. Separating your business logic from your presentation is a great way to improve readability and maintainability.

Create template strings and fill them with data as you iterate.

I'd probably pretty up the array declaration for easier "eyeballing".

define('TAX_RATES', [
    'Single' => [
        'Ranges' => [0,  9700, 39475, 84200, 160725, 204100, 510300],
        'MinTax' => [0,   970,  4543, 14382,  32748,  46628, 153798],
        'Rates'  => [10,   12,    22,    24,     32,     35,     37],
    ],
    'Married_Jointly' => [
        'Ranges' => [0, 19400, 78950, 168400, 321450, 408200, 612350],
        'MinTax' => [0,  1940,  9086,  28765,  65497,  93257, 164709],
        'Rates'  => [10,   12,    22,     24,     32,     35,     37],
    ],
    'Married_Separately' => [
        'Ranges' => [0, 9700, 39475,    84200,   160725,   204100,   306175],
        'MinTax' => [0,  970,  4543, 14382.50, 32748.50, 46628.50, 82354.75],
        'Rates'  => [10,  12,    22,       24,       32,       35,       37],
    ],
    'Head_Household' => [
        'Ranges' => [0, 13850, 52850, 84200, 160700, 204100, 510300],
        'MinTax' => [0,  1385,  6065, 12962,  31322,  45210, 152380],
        'Rates'  => [10,   12,    22,    24,     32,     35,     37],
    ]
]);

Code: (Demo -- click the eye icon to see the rendered html)

$tableTemplate = <<<TABLE
<h2>%s</h2>
<table border="1">
    <tr>
        <th>Taxable Income</th>
        <th>Tax Rate</th>
    </tr>
%s
</table>
TABLE;

$rowTemplate = <<<ROW
    <tr>
        <td>%s</td>
        <td>%s%d%%</td>
    </tr>
ROW;

foreach (TAX_RATES as $status => $data) {
    $rows = [];
    $count = count($data['Rates']);
    for ($i = 0; $i < $count;   $i) {
        $rows[] = sprintf(
            $rowTemplate,
            isset($data['Ranges'][$i   1])
                ? '$' . number_format($data['Ranges'][$i]   ($i ? 1 : 0)) . ' - $' . number_format($data['Ranges'][$i   1])
                : "> $" . number_format($data['Ranges'][$i]),
            $data['MinTax'][$i] ? '$' . number_format($data['MinTax'][$i], 2) . '   ' : '',
            $data['Rates'][$i]
        );
    }
    printf($tableTemplate, $status, implode("\n", $rows));
}

Notice that a literal % in the template strings must be "escaped" by another %. Otherwise, mark variable strings as %s, variable integers as %d, and floats as %f. This is a basic rundown, but there are more formatting features that you can enjoy with the printf() family of functions. (sprintf() is the "silent" version of printf() that just returns its payload instead of printing it.)

Add money formatting as you wish.

  • Related