The ids of a database table have numbers. Instead of writing them on the page in length I want to shorten it. If the result is 1-10 that’s how I want it written. If the result is non-sequential such as 2, 4, 9, 14 I need to include commas. Or mixed 1, 3, 6-10.
How would the for loop work?
while($row = mysql_fetch_array($result)){
for($i=0; $i<count($COLORS); $i++){
if($row["txtarea".$i]!==""){
$txtarea[]= $row["txtarea".$i];
//echo $row["txtarea".$i]."<br />\
";
}
}
//print_r($txtarea);
$totalTxtarea[]= $txtarea; //array of $txtarea
$blid[] = $row["blid"];
$bibleid0[] = $row["id0"];
$bookTitle0[] = $row["bookTitle0"];
$book0[] = $row["book0"];
$chapter0[] = $row["chapter0"];
$verse0[] = (int)$row["verse0"];
$bibleid1[] = $row["id1"];
$bookTitle1[] = $row["bookTitle1"];
$book1[] = $row["book1"];
$chapter1[] = $row["chapter1"];
$verse1[] = (int)$row["verse1"];
$comments[] = $row["comments"];
$username[] = $row["username"];
$date[] = $row["date"];
}
for($i=0; $i<count($blid); $i++){
?>
<span style="float: left; text-align: left; font-family: Arial, Helvetica, sans-serif; font-size: 11px; display: block; margin: 5px 5px 0px 5px; width: 90%; border: 1px solid #505050; padding: 2px 2px 0px 2px;">
<?php
//print_r($totalTxtarea[$i]);
echo "<a href=\\"JavaScript:;\\" style=\\"font-weight: bold;\\" onmouseover=\\"this.title='";
//echo count($txtarea);
for($j=0; $j<count($totalTxtarea[$i]); $j++){
echo $totalTxtarea[$i][$j];
//echo $txtarea[$j];
if($j<count($totalTxtarea[$i])-1){
echo " + ";
}
}
echo "';\\" onmouseout=\\"this.title='';\\" title=\\"\\">".$bookTitle0[$i]." ".$chapter0[$i].":";
$t=explode("+", $verse0[$i]);
//print_r($t);
/*******************************************************************************************************/
//$id=array();
//while($row = mysql_fetch_array($result)){
// $id[] = (int)$row["id"];
//}
sort($t); //sort the array in numerical order
$prev_verse=0; //the previous id
$prev_was_sequential=false; //was the previous id in sequential order?
$numlist=""; //the list of numbers to print out
for($i=0;$i<count($t);$i++){
if($i>0){ //if this is not the first id in the array
if($prev_verse+1==$t[$i]){
$prev_was_sequential=true; //the previous number was in sequence
if($i+1==count($t)){
$numlist.="-".$t[$i]; //if this is the last id and there was a sequence up to the last id
}
}
elseif($prev_was_sequential===true){ //if the current number was not in sequence, but the previous one was
$numlist.="-".$prev_verse.", ".$t[$i];
$prev_was_sequential=false;
}
else{ //the number was not in sequence
$numlist.=", ".$t[$i];
$prev_was_sequential=false;
}
}
else{ //if this is the first id in the array
$prev_id=$t[$i];
$numlist.=$t[$i];
}
$prev_verse=$t[$i];
}
echo $numlist;
There’s probably a way to refactor this since it seems a bit like spegetti code, but it seems to work:
$id=array();
while($row = mysql_fetch_array($result)){
$id[] = (int)$row["id"];
}
sort($id); //sort the array in numerical order
$prev_id=0; //the previous id
$prev_was_sequential=false; //was the previous id in sequential order?
$numlist=""; //the list of numbers to print out
for($i=0;$i<count($id);$i++){
if($i>0){ //if this is not the first id in the array
if($prev_id+1==$id[$i]){
$prev_was_sequential=true; //the previous number was in sequence
if($i+1==count($id)){
$numlist.="-".$id[$i]; //if this is the last id and there was a sequence up to the last id
}
}
elseif($prev_was_sequential===true){ //if the current number was not in sequence, but the previous one was
$numlist.="-".$prev_id.", ".$id[$i];
$prev_was_sequential=false;
}
else{ //the number was not in sequence
$numlist.=", ".$id[$i];
$prev_was_sequential=false;
}
}
else{ //if this is the first id in the array
$prev_id=$id[$i];
$numlist.=$id[$i];
}
$prev_id=$id[$i];
}
echo $numlist;
Looks short and sweet. But How do you remove the quotes “” and string(). Also If there’s only 1 number in the array then there shouldn’t be any commas following that.
To only have the appropriate number of commas, first push the values on to an array, and then join them together with commas by using the implode command.
You also won’t need to test $end, because you can join together $start and $end with the dash. The dash will only appear if both values exist, for which you can use array_filter to remove values that are equivalent to false.
The steps are:
[list=1][]put $start and $end into their own array
[]filter the array with array_filter
[]join the contents of the array with ‘-’
[]add the joined result to a separate array for the result
[*]afterwards, join the results with ', '[/list]
Another approach would be to use array_reduce to tease the data into another form.
Here’s an example which groups the ranges together and returns an array in the style array(1,“3-5”,9) which may or may not be useful for the OP. Alternatively, the output string (comma-separated, or whatever you like) could be done directly in the reducing function but I think keeping an array is more flexible.
Reducing Function
function reduce_ranges($reduced, $value) {
static $in_range, $previous;
// Reset
if ($in_range === NULL) {
$in_range = FALSE;
$previous = NULL;
}
// In a range
if (isset($previous) && $value == $previous + 1) {
if (!$in_range) {
$in_range = TRUE;
}
// Update the range
end($reduced);
$key = key($reduced);
$start = strtok($reduced[$key], "-");
$reduced[$key] = $start."-".$value;
// Not in a range
} else {
$reduced[] = $value;
$in_range = FALSE;
}
$previous = $value;
return $reduced;
}
Sample Use
// Sample array of numbers
$data = array_merge(
array(1, 2, 17, 3, 4, 5, 25),
range(100,105)
);
// sort the array in ascending order
sort($data, SORT_NUMERIC);
$ranges = array_reduce($data, "reduce_ranges");
echo implode(",", $ranges) . PHP_EOL;