Hi Everyone!

I'm quite confused as to how to implement usort correctly. I'm trying to sort values in a multidimensional array by smallest to largest distance.

Here is my code:


// the distance has been calculated and  the values have been put into an array

//begin while loop.....

foreach ($_SESSION['distances'] as $dists) {

		$sortDistance=$dists["distances".$i];

		}// end foreach $_SESSION['distances'] 

// use usort to sort array $_SESSION['distances'] 

$myarray=$_SESSION['distances'];

usort($myarray,'sortDist');

print_r($_SESSION['distances']);


}// end while loop....



function sortDist($a,$b){

echo "sortdist function running";
 if ($a == $b) {return 0;}
  return ($a - $b) ? -1 : 1;



}// end sortDist()



Question:

I've been researching usort and it is unclear why I need two variables, $a and $b when i only have one variable to sort with: $sortDistance. I tried to rewrite it like this with no success:

function sortDist($sortDistance,$sortDistance){

echo "sortdist function running";
 if ($a == $b) {return 0;}
  return ($a - $b) ? -1 : 1;
}

I'm stuck on how to sort this multidimensional array correctly, so any suggestions would be extremely helpful.

    Leoa wrote:

    I've been researching usort and it is unclear why I need two variables, $a and $b when i only have one variable to sort with: $sortDistance

    But you don't have one value, you have a whole list of them; and [man]usort[/man] passes your comparison function pairs of values to compare and see which is larger.

    Of course, for such a trivial task as sorting a list of numbers in numeric order, plain ordinary [man]sort[/man] would be sufficient.

    $myarray=$_SESSION['distances'];
    
    usort($myarray,'sortDist');
    
    print_r($_SESSION['distances']);
    

    You won't see any difference because you're sorting $myarray but printing $_SESSION['distances'].

      I'm still unable to get this code to work properly. I looked around for code that is similar what I'm trying to do. and I found this:

      
      
      $inventory = array(
      
         array("type"=>"fruit", "price"=>3.50),
         array("type"=>"milk", "price"=>2.90),
         array("type"=>"pork", "price"=>5.43),
      
      );
      $price = array();
      
      foreach ($inventory as $key => $row)
      {
          $price[$key] = $row['price'];
      }
      array_multisort($price, $inventory);
      
      
      print_r($inventory);
      
      
      

      //output Array ( [0] => Array ( [type] => milk [price] => 2.9 ) [1] => Array ( [type] => fruit [price] => 3.5 ) [2] => Array ( [type] => pork [price] => 5.43 ) )
      This code sorts the array by ascending order of the price value.

      In my code I tried to adapt the code above:

      
       $distances = array($event_id =>
      		array("event_name"=>$event_name,"distances"=>$distance)
      
      		);
      
      $dist = array();
      
      foreach ($distances as $key => $row)
      {
             $dist[$key] = $row['distances'];
      }
      
      var_dump($dist);
      var_dump($distances);
      
      array_multisort($dist, SORT_ASC,$distances);
      
      echo "<br>";
      
      print_r($distances);
      
      
      
      

      out put:

      ////////vardump output for $dist:
      array(1) { [1]=> float(135.23270826418) }

      array(1) { [2]=> float(57.790571453271) }

      array(1) { [3]=> float(135.81250714615) }

      array(1) { [4]=> float(134.83200519242) }

      array(1) { [5]=> float(135.68732962083) }

      ////////vardump output for $distance:
      array(1) { [1]=> array(2) { ["event_name"]=> string(9) "Kotoricon" ["distances"]=> float(135.23270826418) } }

      array(1) { [2]=> array(2) { ["event_name"]=> string(5) "I-CON" ["distances"]=> float(57.790571453271) } }

      array(1) { [3]=> array(2) { ["event_name"]=> string(12) "LunaCon 2012" ["distances"]=> float(135.81250714615) } }

      array(1) { [4]=> array(2) { ["event_name"]=> string(6) "Otakon" ["distances"]=> float(134.83200519242) } }

      array(1) { [5]=> array(2) { ["event_name"]=> string(18) "New York comic Con" ["distances"]=> float(135.68732962083) } } */

      //////print_r output
      Array ( [0] => Array ( [event_name] => Kotoricon [distances] => 135.23270826418 ) )

      Array ( [0] => Array ( [event_name] => I-CON [distances] => 57.790571453271 ) )

      Array ( [0] => Array ( [event_name] => LunaCon 2012 [distances] => 135.81250714615 ) )

      Array ( [0] => Array ( [event_name] => Otakon [distances] => 134.83200519242 ) )

      Array ( [0] => Array ( [event_name] => New York comic Con [distances] => 135.68732962083 ) )

      Please note above that all the top level Array[] have Array[0].
      I'm not sure why the array is not being sorted since this the same technique used in the example I found above.

      I noticed that when I add [$event_id] line to the foreach loop:

      foreach ($distances[$event_id] as $key => $row)
      {
      
      
      $dist[$key] = $row['distances'];
      //echo  "key is ".$dist[$key]."<br>";
      }
      
      

      I get some very strange results

      output:

      Warning: array_multisort() [function.array-multisort]: Array sizes are inconsistent in C:\xampp\htdocs\otakufinder\scripts\geoloco.php on line 98

      Array ( [1] => Array ( [event_name] => Kotoricon [distances] => 135.23270826418 ) )

      Warning: array_multisort() [function.array-multisort]: Array sizes are inconsistent in C:\xampp\htdocs\otakufinder\scripts\geoloco.php on line 98

      Array ( [2] => Array ( [event_name] => I-CON [distances] => 57.790571453271 ) )

      Warning: array_multisort() [function.array-multisort]: Array sizes are inconsistent in C:\xampp\htdocs\otakufinder\scripts\geoloco.php on line 98

      Array ( [3] => Array ( [event_name] => LunaCon 2012 [distances] => 135.81250714615 ) )

      Warning: array_multisort() [function.array-multisort]: Array sizes are inconsistent in C:\xampp\htdocs\otakufinder\scripts\geoloco.php on line 98

      Array ( [4] => Array ( [event_name] => Otakon [distances] => 134.83200519242 ) )

      Warning: array_multisort() [function.array-multisort]: Array sizes are inconsistent in C:\xampp\htdocs\otakufinder\scripts\geoloco.php on line 98

      Array ( [5] => Array ( [event_name] => New York comic Con [distances] => 135.68732962083 ) )

      Questions:

      1.a I get a warning and all the top level Arrays have unique indexes. Please let me know why The Top level Array sometimes does not get a index of 0? Is this the same array being overwritten in the foreach loop? Because of that, this is why the sort is failing?

      1.b When you compare the vardump from distances and dist, the sizes are consistent. The warning can also be from a syntax error. However I'm not missing any commas or quotes. Can there be another reason for the warning?

      1. Is the array and foreach code written correctly? Do you know of another example I can follow?

        it's a little buggy but I got it to work. I thought the while loop that bring in data from the DB wold work on the array and increment the values in the array. However, i needed to use push_arrray inoder to accomplish this. Once I had access to the values outside the while loop, the sort function worked. yah!

        <?php
        
        
        
        include('database_connect.php');
        ini_set('display_errors',1);
         error_reporting(E_ALL);
        /////////////////////////////////////////////////////////////////////////
        
        session_start();
        
        $_POST['userLong']=-73.9599609375;
        
        $_POST['userLat']=40.8169272319157;
        
        if(isset($_POST['userLat']) && isset($_POST['userLong'])){
        
        $userLong=(float)$_POST['userLong'];
        
        $userLat=(float)$_POST['userLat'];
        // select a range of numbers
        // selcet a range of dates
        // or selcet all evetns id, name long and lat then compare them here.
        
        $query1 = "SELECT * FROM events";
        
        echo $query1."<br>";
        
        $events;
        
        $i=0;
        $a;$b;
         $distances ="";
        $dist_id="";
        	$results1=mysql_query($query1);
        
        	while ($row= mysql_fetch_array($results1))	{
        
        		$event_id = $row['id'];
        
        		$event_name=$row['event_name'];
        
        		$longitude = $row['longitude'];
        
        		$latitude= $row['latitude'];
        
        
        
        
        		$_SESSION['events']	=$events=array(
        
        			$event_id => array(
        					"event_name"=>$event_name,
        					"long"=>$longitude,
        					"lat"=>$latitude)
        					);
        
        
        		foreach ($_SESSION['events'] as $event) {
        
        		//	echo $event["long".$i];
        		$eventLong=$event["long"];
        		$eventLat= $event["lat"];
        
        			$distance = getDistance($userLat,$eventLat, $userLong, $eventLong);
        			// capare user data to database long and lat;
        			//echo $distance;
        			//push in new array
        
        			//sort array which has the lease differance to greates distance ( small to big number)
        
        
        
        		}// end foreach event
        
        	echo  "<br>";
        
        
        	///array to put new distance values into
        
        foreach ($_SESSION['events'] as $event) {
        
         array_push($_SESSION['distances'], $distances= array(array("event_name"=>$event_name,"distance"=>$distance)));
        
        }
        
        
        
        	$i++;
        
        	}// end while loop
        
        
        }// end program
        
        function getDistance($lat1,$lat2,$lon1,$lon2){
        
        
        $lat1 = (float) $lat1;
        $lat2 = (float) $lat2;
        $lon1 = (float) $lon1;
        $lon2 = (float) $lon2;
        
         $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);
        
        return $dist;
        	}
        
        print_r($_SESSION['distances']);
        
        echo "<br>";
        
        $dist = array();
        
        foreach ($_SESSION['distances'] as $key => $row)
        {
            $dist[$key] = $row['distance'];
        	//echo  "key is ".$dist[$key]."<br>";
        }
        
        //var_dump($dist)."<br>";
        //var_dump($distances)."<br>";
        array_multisort($dist, SORT_ASC,$_SESSION['distances']);
        //unset($_SESSION["distances"]);
        print_r($_SESSION['distances']);
        ?>

          Now that I've seen the context:

          $query1 = "SELECT id, event_name, latitude, longitude FROM events";
          $results1 = mysql_query($query1); // Note: the MySQL extension should not be used for new development
          $events = array();
          while($row = mysql_fetch_array($results1))
          {
              $event_id = $row['id'];
              $event_name = $row['event_name'];
              $event_latitude = $row['latitude'];
              $event_longitude = $row['longitude'];
              $event_distance = getDistance($user_latitude, $event_latitude, $user_longitude, $event_longitude);
              $events[$event_id] = array('event_name' => $event_name, 'long' => $event_longitude, 'lat' => $event_latitude, 'distance' => $event_distance);
          }
          uasort($events, function($a, $b)
          {
              if($a['distance'] < $b['distance']) return -1;
              if($a['distance'] > $b['distance']) return 1;
              return 0;
          });
          

          Or, assuming MySQL has the functions...

          $userLat = deg2rad($userLat);
          $userLong = deg2rad($userLong);
          $query1 = "SELECT id, event_name, (sin($userLat) * sin(latitude) +  cos($userLat) * cos(latitude) * cos($userLong - longitude)) AS distance FROM events ORDER BY distance";
          ...
          

            Thanks Weedpacket, your code is for more elegant than mine! I'm taking notes...

              Write a Reply...