1

I'm using the following code to get the distance between location.

<?php
function curl_request($sURL,$sQueryString=null)
{
        $cURL=curl_init();
        curl_setopt($cURL,CURLOPT_URL,$sURL.'?'.$sQueryString);
        curl_setopt($cURL,CURLOPT_RETURNTRANSFER, TRUE);
        $cResponse=trim(curl_exec($cURL));
        curl_close($cURL);
        return $cResponse;
}

$sResponse=curl_request('http://maps.googleapis.com/maps/api/distancematrix/json?units=imperial&origins=London&destinations=Southend-on-sea|Westcliff-on-sea|Leigh-on-sea|leeds&mode=driving&language=en&sensor=false');
$oJSON=json_decode($sResponse);
if ($oJSON->status=='OK')
        $fDistanceInMiles=(float)preg_replace('/[^\d\.]/','',$oJSON->rows[0]->elements[0]->distance->text);
else
        $fDistanceInMiles=0;

echo 'Distance in Miles: '.$fDistanceInMiles.PHP_EOL;

?>

-

This will only get the first value in the JSON response because of this:

$fDistanceInMiles=(float)preg_replace('/[^\d\.]/','',$oJSON->rows[0]->elements[0]->distance->text);

-

The JSON looks like this:

{
   "destination_addresses" : [
      "Southend-on-Sea, UK",
      "Westcliff-on-Sea, Southend-on-Sea, UK",
      "Leigh-on-Sea SS9, UK",
      "Leeds, UK"
   ],
   "origin_addresses" : [ "London, UK" ],
   "rows" : [
      {
         "elements" : [
            {
               "distance" : {
                  "text" : "42.0 mi",
                  "value" : 67669
               },
               "duration" : {
                  "text" : "1 hour 14 mins",
                  "value" : 4464
               },
               "status" : "OK"
            },
            {
               "distance" : {
                  "text" : "42.7 mi",
                  "value" : 68723
               },
               "duration" : {
                  "text" : "1 hour 17 mins",
                  "value" : 4646
               },
               "status" : "OK"
            },
            {
               "distance" : {
                  "text" : "40.1 mi",
                  "value" : 64508
               },
               "duration" : {
                  "text" : "1 hour 10 mins",
                  "value" : 4225
               },
               "status" : "OK"
            },
            {
               "distance" : {
                  "text" : "195 mi",
                  "value" : 313043
               },
               "duration" : {
                  "text" : "3 hours 39 mins",
                  "value" : 13133
               },
               "status" : "OK"
            }
         ]
      }
   ],
   "status" : "OK"
}

So when i run my code, I get this printed on my page:

Distance in Miles: 42 

But what I need is to print out the highest number. So it should be like this:

Distance in Miles: 195

Could someone please advise on this?

Thanks in advance.

5
  • 1
    php.net/manual/en/function.array-reduce.php Commented Jun 14, 2017 at 20:20
  • 1
    Are you asking us how to iterate over an array and check for a condition to hold? Commented Jun 14, 2017 at 20:21
  • Possible duplicate of Finding the max value of an attribute in an array of objects Commented Jun 14, 2017 at 20:27
  • 2
    @zod Although the algorithms used in your links is what the OP wants, this is a PHP question. Commented Jun 14, 2017 at 20:31
  • Did you give up? Commented Jun 29, 2017 at 18:31

5 Answers 5

3

With array_column() you can extract all the distance arrays and then build a lookup with text as the key and value as the value:

$array = json_decode($json, true);
$dist  = array_column(array_column($array['rows'][0]['elements'], 'distance'),
                                   'value', 'text');

Then just compute the max(), find it and outpout the key:

echo array_search(max($dist), $dist);
Sign up to request clarification or add additional context in comments.

3 Comments

Neat. I suppose you could sort/reverse sort and grab the appropriate element too right?
This does what I need to do but why Can't i remove the "mi" ? I tried this: $dist = preg_replace('mi','',$dist); echo array_search(max($dist), $dist);
You need to replace on the return of array_search(), but you could take value which is meters and divide by 1609.34 to get miles. Or cast to a float echo (float)array_search(max($dist), $dist);
1

For this, you can collect all text, (try using array_column()) keys in an array then find maximum value using max()

2 Comments

While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From Review
Thanks, @Derek for your concern
1

I don't know if this is the simpler way, but give this a try.

do something like this before printing in the screen.

$lenght_elements=sizeof($oJSON->rows[0])
$array_elements=array();
for($i=0;$i<$lenght_elements;$i++){
$fDistanceInMiles=(float)preg_replace('/[^\d\.]/','',$oJSON->rows[0]->elements[$i]->distance->text);
array_push($array_elements,$fDistanceInMiles);
}

$max_value=max($array_elements); 

echo echo 'Distance in Miles: '.$max_value; //this should print the highest value

NOTE: if you need to run through the rows too, you could use another loop, you'll get your result anyway.

Comments

1

Keep it simple.

// get all elements
$elements = json_decode($oJSON)->rows[0]->elements;

// get all the distances
// array_map() is useful here b/c there is a 1-1 correspondence between an element and its distance
$distances = array_map(function ($element) {
    // convert distance to numeric value to ensure that we are only working with numbers (and not strings)
    return (float) preg_replace('/[^\d\.]/','', $element->distance->text);
}, $elements);

// get the maximum value
echo 'Distance in Miles: ' . max($distances);

Comments

1

Here's how you'd do it with array reduce:

<?php

$json = '{
   "destination_addresses" : [
      "Southend-on-Sea, UK",
      "Westcliff-on-Sea, Southend-on-Sea, UK",
      "Leigh-on-Sea SS9, UK",
      "Leeds, UK"
   ],
   "origin_addresses" : [ "London, UK" ],
   "rows" : [
      {
         "elements" : [
            {
               "distance" : {
                  "text" : "42.0 mi",
                  "value" : 67669
               },
               "duration" : {
                  "text" : "1 hour 14 mins",
                  "value" : 4464
               },
               "status" : "OK"
            },
            {
               "distance" : {
                  "text" : "42.7 mi",
                  "value" : 68723
               },
               "duration" : {
                  "text" : "1 hour 17 mins",
                  "value" : 4646
               },
               "status" : "OK"
            },
            {
               "distance" : {
                  "text" : "40.1 mi",
                  "value" : 64508
               },
               "duration" : {
                  "text" : "1 hour 10 mins",
                  "value" : 4225
               },
               "status" : "OK"
            },
            {
               "distance" : {
                  "text" : "195 mi",
                  "value" : 313043
               },
               "duration" : {
                  "text" : "3 hours 39 mins",
                  "value" : 13133
               },
               "status" : "OK"
            }
         ]
      }
   ],
   "status" : "OK"
}';

$maxDistance = array_reduce(json_decode($json, true)["rows"][0]["elements"], function($accumulator, $item){
   return ($item['distance']['value'] > $accumulator) ? $item['distance']['value'] : $accumulator;
}, 0);


var_dump($maxDistance);

Yields:

int(313043)

Here's the same code without the unnecessary conversion to an object:

$distance = array_reduce(json_decode($json)->rows[0]->elements, 
function($accumulator, $item){
    return ($item->distance->value > $accumulator) ? $item->distance->value : $accumulator;
}, 0);

If you didn't want to reconvert to miles, you could do the reduce on the float value of the text field instead.

http://sandbox.onlinephpfunctions.com/code/37176c07b7fc46a713b275e2d3326444b970de1a

My guess is that this is the most performant way to do it if you have a large array.

2 Comments

My only critic would be the unnecessary conversion to an array.
@Mikey I've added the object version.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.