Link to home
Start Free TrialLog in
Avatar of neilsav
neilsav

asked on

How to store multiple values in a PHP array, find the lowest 3 values then display

What I am trying to do:
My website is a public golf course review website - thelocalgolfer.com -
I have a single page for each golf course, on the page I would like to display the closest 5 courses mileage wise on the course display page.  All of the course pages are built dynamically so what happens is I pass a course # to the page, it queries a mysql dbase and grabs all pertinent course information - e.g. course name, latitude, longitude, etc..

I then have another query that pulls the latitude and longitude of a bunch of courses that are near based on region - I then pass each of those latitude and longitude #'s in to a distance function that calculates the mileage distance away from the course that I am displaying on the page.  I store all of the distances in a an array, but I don't know what to do next.  Here is the code so far:

//This function will compare the course and the courses in the same region as that course and return a distance in mileage
function distance($lat1, $lon1, $lat2, $lon2, $unit) { 

  $theta = $lon1 - $lon2; 
  $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) +  cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta)); 
  $dist = acos($dist); 
  $dist = rad2deg($dist); 
  $miles = $dist * 60 * 1.1515;
  $unit = strtoupper($unit);

  if ($unit == "K") {
    return ($miles * 1.609344); 
  } else if ($unit == "N") {
      return ($miles * 0.8684);
    } else {
        return $miles;
      }
}

//The array that stores the mileage away from the course that I am displaying
$course_distance= array();
//grabbing all returned records from database comparing the lat and lon vs. the course displayed on the page
while ($z < $nummile) {
//The course id needed for the hyperlink
$id=mysql_result($resultmile,$z,"id");

$course_name=mysql_result($resultmile,$z,"course_name");

$latC=mysql_result($resultmile,$z,"lat");
$lonC=mysql_result($resultmile,$z,"lon");

echo $course_name . " ";
echo distance($lat, $lon, $latC, $lonC, "m") . " miles<br>";
$distanceq=distance($lat, $lon, $latC, $lonC, "m");

$course_distance[] = $distanceq;

  $z++;
					   }

//This will get the course closest, but it doesn't get the three closest and doesn't return coursename or courseid
echo min($course_distance);

Open in new window


I want to take 3 variables- the mileage of the closest course (which comes as an output from the distance function, the course name, and the course id (which I need for the hyperlink).  I then want to display this information.

I am familiar with php, but not so familiar with array's and multidimensional arrays. I do not want to store these values in a dbase, or flatfile, I would like to do all of the calculations on the page itself.  Also, maybe arrays is not the best way, I am open to any other way to accomplish the goal of displaying the 5 closest courses to the subject course.  If you want to see the type of  page that I will display this information check it out here:  http://www.thelocalgolfer.com/course_info_display-course-7.html
Avatar of Member_2_248744
Member_2_248744
Flag of United States of America image

greetings neilsav, , I would think that the array is a good method for what you say you need. . .
what I might try is to place the Course Name ans ID in the array KEY value

$course_distance[$course_name.'|'.$id] = $distanceq;

I would try the PHP asort() function to order these distance numbers AND keep the associated KEYS
asort($course_distance);

next you might try a foreach with $course_distance array
foreach($course_distance as $key => $value) {$keys=split('|',$key);
echo 'course- '.$keys[0].' ID- '.$keys[1].' distance- '.$value.'<br />';
}


I hope this gives you enough to get the methods, The above is UNTESTED code, so may hvae syntax errors, but the idea should be there for you

Ask questions if you need more Info. . .
Avatar of neilsav
neilsav

ASKER

Slick -

Thanks so much for taking time to help me with this problem.  We are very close -

First I used the explode function vs. split because the split function is depricated as of php 5.3.

Beyond that, I have all the data I need, I just need to know how to get the 5 closest records.  In other words, the record that have the smallest 5 distance values.

I have attached the latest code:
//This function will compare the course and the courses in the same region as that course and return a distance in mileage
function distance($lat1, $lon1, $lat2, $lon2, $unit) { 

  $theta = $lon1 - $lon2; 
  $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) +  cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta)); 
  $dist = acos($dist); 
  $dist = rad2deg($dist); 
  $miles = $dist * 60 * 1.1515;
  $unit = strtoupper($unit);

  if ($unit == "K") {
    return ($miles * 1.609344); 
  } else if ($unit == "N") {
      return ($miles * 0.8684);
    } else {
        return $miles;
      }
}

//The array that stores the mileage away from the course that I am displaying
$course_distance= array();
//grabbing all returned records from database comparing the lat and lon vs. the course displayed on the page
while ($z < $nummile) {
//The course id needed for the hyperlink
$id=mysql_result($resultmile,$z,"id");

$course_name=mysql_result($resultmile,$z,"course_name");

$latC=mysql_result($resultmile,$z,"lat");
$lonC=mysql_result($resultmile,$z,"lon");

echo $course_name . " ";
echo distance($lat, $lon, $latC, $lonC, "m") . " miles<br>";
$distanceq=distance($lat, $lon, $latC, $lonC, "m");

$course_distance[$course_name.'|'.$id] = $distanceq;

  $z++;
					   }

//This will get the course closest, but it doesn't get the three closest and doesn't return coursename or courseid
echo min($course_distance);

//print_r($course_distance);

echo "<br />";

foreach($course_distance as $key => $value) {$keys=explode('|',$key);
echo ''.$keys[1].' course- '.$keys[0].' distance- '.$value.'<br />';
}

?>

Open in new window


Thanks,
Neil
ASKER CERTIFIED SOLUTION
Avatar of Member_2_248744
Member_2_248744
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
change the
 if ($count>2) break;

to

 if ($count>4) break;

for a Five value print out, sorry I was not consentrating on your number " the 5 closest records"
Avatar of neilsav

ASKER

Excellent - that worked perfectly.  I appreciate your help!

Quick question - I found that the first record is always the  same course that I am comparing it to (which makes sense).  Since I don't want the course itself to come up,  I threw in an if statement to basically not echo the first record coming, is there a better way to do it?

 
$value=round($value,1);
echo "<a href='course_info_display-course-$keys[1].html'>$keys[0]</a> is $value miles away<br />";
}
if($count>4) break;
++$count;

}

Open in new window

Avatar of neilsav

ASKER

Awesome a great help!
Avatar of neilsav

ASKER

Sorry this is the code - the code posted above is incomplete
foreach($course_distance as $key => $value) {$keys=explode('|',$key);
if($count>0) {

$value=round($value,1);
echo "<a href='course_info_display-course-$keys[1].html'>$keys[0]</a> is $value miles away<br />";
}
if($count>4) break;
++$count;

}

Open in new window

If it works, that's what counts!
But i would probally use the PHP continue;

foreach($course_distance as $key => $value) {$keys=explode('|',$key);
if($count==0){
    ++$count;
    continue;}

$value=round($value,1);
echo "<a href='course_info_display-course-$keys[1].html'>$keys[0]</a> is $value miles away<br />";
if($count>5) break;// change for 5 output
++$count;
}

mine is not really better, just different, you might even place the ++count; at the begining and increase the if($count>5)


foreach($course_distance as $key => $value) {$keys=explode('|',$key);
++$count;
if($count==1) continue;

$value=round($value,1);
echo "<a href='course_info_display-course-$keys[1].html'>$keys[0]</a> is $value miles away<br />";
if($count>6) break;// change for 5 output
}