Reputation: 1434
So, I have a two-dimensional array:
$fruits = array
(
array('fruit' => 'Apple', 'rating' => '2'),
array('fruit' => 'Pear', 'rating' => '3'),
array('fruit' => 'Peach', 'rating' => '2'),
array('fruit' => 'Strawberry', 'rating' => '2')
);
I need to get an explicit order. Therefore, taking the example above, I want to display a table
containing three col
s -> fruit, rating and rank. If there is any equality in the ratings then I want to have radio buttons
in the third col with the possible ranks. This is what I mean:
So far I have the below piece of code which is only capable to tell whether there is another fruit with the same rating, and if yes it shows radios from 1-4. This is a very rude solution. So how can I easily build it up taking the fact into consideration that the rating can be anything. For e.g. 2-2-3-3 in which case I need radios 1-2,1-2 and 3-4,3-4.
PHP:
echo "<table><tr><td>fruit</td><td>rating</td><td>rank</td></tr>";
for($i = 0; $i < count($fruits); ++$i) {
echo "<tr><td>".$fruits[$i]['fruit']."</td><td>".$fruits[$i]['rating']."</td><td>";
for($j = 0; $j < count($fruits); ++$j) {
if($i != $j) {
if($fruits[$i]['rating'] == $fruits[$j]['rating']) {
echo "<input type=\"radio\" name=\"".$fruits[$i]['fruit']."\" value=\"1\">1
<input type=\"radio\" name=\"".$fruits[$i]['fruit']."\" value=\"2\">2
<input type=\"radio\" name=\"".$fruits[$i]['fruit']."\" value=\"3\">3
<input type=\"radio\" name=\"".$fruits[$i]['fruit']."\" value=\"4\">4"
break;
}
else if ($j == 3)
{
echo "<b>".($i+1)."</b></td></tr>";
}
}
else if ($j==3)
{
echo "<b>".($i+1)."</b></td></tr>";
}
}
}
echo "</table>";
Basically I need to have a count per rating for all the cases there is an equality.
P.S.: The array is already DESC
sorted based on the ratings, this is why ($i+1)
works in my code.
Upvotes: 1
Views: 259
Reputation: 324690
Since you already have a pre-sorted array, what you need is to find ranges.
Once you have the range, you can then output that set of rows.
Here's an example:
echo "<table><tr><td>fruit</td><td>rating</td><td>rank</td></tr>";
$total = count($fruits);
for( $i=0; $i<$total; $i=$range_end+1) {
$range_start = $i;
while($i+1 < $total && $fruits[$i]['rating'] == $fruits[$i+1]['rating']) {
$i++;
}
$range_end = $i;
$range = array_slice($fruits, $range_start, $range_end-$range_start+1);
foreach($range as $fruit) {
echo "<tr>"
."<td>".$fruit['fruit']."</td>"
."<td>".$fruit['rating']."</td>"
."<td>";
if( $range_start == $range_end) {
echo $fruit['rating'];
}
else {
for($j=$range_start; $j<=$range_end; $j++) {
echo '<input type="radio" name="'.$fruit['fruit'].'" value="'.$j.'">'.$j;
}
}
echo "</td>"
."</tr>";
}
}
echo "</table>";
Note the slightly unconventional for $i
loop. What's happening here is that we're starting the loop at 0, recording the position we are at in $range_start
, then advancing until the next fruit's rating is different. At that point we have $range_end
, which may be the same as $range_start
if there are no fruits with the same rating. Then we extract the range from the $fruits
array and output it. Once that is done, the loop continues one place past the end of the range we just did.
Upvotes: 1
Reputation: 129
Take a look on usort(). This can re-order your array (or clone it) based on a custom function.
Upvotes: 0
Reputation: 350365
Here is what I would suggest:
$fruits = array(
array('fruit' => 'Apple', 'rating' => '2'),
array('fruit' => 'Pear', 'rating' => '3'),
array('fruit' => 'Peach', 'rating' => '2'),
array('fruit' => 'Strawberry', 'rating' => '2')
);
// get unique ratings, in descending order
$ratings = array_unique(array_column($fruits, 'rating'));
sort($ratings);
$ratings = array_fill_keys(array_reverse($ratings), array());
// put fruits in their respective rating buckets:
foreach($fruits as $fruit) {
$ratings[$fruit['rating']][] = $fruit['fruit'];
}
// Generate the HTML table
$html = "<table border=1><tr><th>fruit</th><th>rating</th><th>rank</th></tr>";
$rank = 1;
foreach($ratings as $rating => $fruits) {
foreach($fruits as $fruit) {
if (count($fruits) === 1) {
$rankHtml = "<b>$rank</b>";
} else {
$rankHtml = "";
for ($i = $rank; $i < $rank + count($fruits); $i++) {
$rankHtml .= "<input type='radio' name='$fruit' value='$i'>$i";
}
}
$html .= "<tr><td>$fruit</td><td>$rating</td><td>$rankHtml</td></tr>\n";
}
$rank += count($fruits);
}
$html .= "</table>";
echo $html;
As you can see I like to separate the logic from the output. The only echo
is at the end.
The main characteristic of this method is the intermediate structure, where the fruit names are grouped into separate arrays depending on their common rating. This, I think, results in nicer code.
Upvotes: 0