How to return elements of an array with the highest values?

I'd change the keys and values in the array, then sort by key and return the values of the first key:

$ages = array("Peter" => "35", "Ben" => "37", "Joe" => "43", "Rob" => "43");
$new = array();

foreach ($ages as $name => $age) {
  $new[$age][] = $name;
}

uksort($new, function($ka, $kb) { return $kb - $ka; }); // or just krsort($new);
$new = array_values($new)[0]; // <- to use this you have to have at least PHP 5.4

// if you have PHP < 5.4 you can simply do it in two steps:
// $new = array_values($new);
// $new = $new[0];

See it in action!

EDIT: even simpler!

$ages = array("Peter" => "35", "Ben" => "37", "Joe" => "43", "Rob" => "43");
$max = max($ages);
$new = array_keys(array_filter($ages, function ($age) use ($max) { return $age == $max; }));

Use:

$people = array("Peter" => "35", "Ben" => "37", "Joe" => "43", "Rob" => "43");
$max = max($people);
$result = array_filter($people, function($age) use ($max){ return $max == $age; });

The result is:

Array
(
    [Joe] => 43
    [Rob] => 43
)

I like the answer of @matteo-tassinari and @evilive much more and wanted to propose it myself. But since the question of efficency came up, here is a solution using only one loop and therefore has a linear time complexity:

<?php
$max = ~PHP_INT_MAX;
$result = [];
foreach($age as $key => $value) {
    if($value > $max) {
        $result = [ $key => $value ];
        $max = $value;
    }
    if($value == $max) {
        $result[$key] = $value;
    }
}
var_dump($result);

And there exists another solution, that uses bucket sort:

function bucket($ages) {
    $buckets = [];
    foreach($ages as $key => $value) {
      $buckets[$value][] = $key;
    }
    return $buckets[max(array_keys($buckets))];
}

Regarding the discusson about peformance and scalability, I wrote a small benchmark script for four kinds of proposed solutions (loop, sort, filter, bucket):

<?php
function loop($ages) {
    $max = 0;
    $result = [];
    foreach($ages as $key => $value) {
            if($value > $max) {
                    $result = [ $key => $value ];
                    $max = $value;
            }
            if($value == $max) {
                    $result[$key] = $value;
            }
    }
    return array_keys($result);
}

function filter($ages) {
    $max = max($ages);
    $new = array_filter($ages, function ($age) use ($max) { return $age == $max; });
    return array_keys($new);
}

function bucket($ages) {
    $buckets = [];
    foreach($ages as $key => $value) {
            $buckets[$value][] = $key;
    }
    return $buckets[max(array_keys($buckets))];
}


for($n = 2; $n < 10000000; $n*=2) {

    $ages = [];
    for($i = 0; $i < $n; $i++) {
            $ages['name_'.$i] = rand(0,100);
    }

    $start = microtime(true);
    echo $n.';';
    loop($ages);
    echo (microtime(true) - $start).';';
    $start = microtime(true);
    arsort($ages);
    echo (microtime(true) - $start).';';
    $start = microtime(true);
    filter($ages);
    echo (microtime(true) - $start).';';
    bucket($ages);
    echo (microtime(true) - $start).';';
    echo PHP_EOL;
}

Limited Live Test

Please double-check if this is right: Using php-5.6.15 on the command line, my timings look something like this:

elements;loop;sort;filter;bucket
...
4096;0.001507;0.009868;0.01211;0.01453;
8192;0.003704;0.002483;0.02488;0.03035;
16384;0.006660;0.01010;0.05396;0.06723;
32768;0.01417;0.01271;0.09163;0.1163;
...
1048576;0.4227;0.9791;2.983;3.943;
2097152;0.8572;2.320;6.064;8.020;
4194304;1.787;4.981;11.90;16.04;
8388608;3.892;10.84;24.76;33.31;

For small number of elements, the difference between the methods is not really big, but as you can see, for the largest value the loop method is two times faster than sort, 8 times faster than filter and eleven times faster than bucket. So if your array is huge, you should use loop.


Just check it manually:

$age = array("Peter" => "35", "Ben" => "37", "Joe" => "43", "Rob" => "43");
$new_array = array();
arsort($age);
$new_array = $age;
$max = max($new_array);

$results = array();
foreach ($new_array as $key => $val) {
    if ($val == $max) {
        $results[] = $key;
    }
}

echo implode(' and ', $results);
// will output "joe and bob"

Tags:

Php