uno
uno

Reputation: 867

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

In my code I have two elements which has the same age "Joe"=>"43" and "Rob"=>"43" .

My code output is:

Joe

I want to output:

Joe and Rob

Because they has the highest value.

This is my code:

<?php
    $cur = 1;

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

    while ($cur > 0) {
        echo $key;
        $cur--;
    }
?>

Upvotes: 16

Views: 6941

Answers (7)

Konrad Gałęzowski
Konrad Gałęzowski

Reputation: 1983

I'm wondering why no one is using built in solution:

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

returns array('Joe', 'Rob')

https://www.php.net/manual/en/function.array-keys.php says:

array_keys ( array $array , mixed $search_value [, bool $strict = FALSE ] ) : array

If a search_value is specified, then only the keys for that value are returned. Otherwise, all the keys from the array are returned.

Upvotes: 1

svrnm
svrnm

Reputation: 1059

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.

Upvotes: 4

Matteo Tassinari
Matteo Tassinari

Reputation: 18584

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; }));

Upvotes: 15

evilive
evilive

Reputation: 1879

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
)

Upvotes: 10

jmattheis
jmattheis

Reputation: 11125

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"

Upvotes: 4

Miguel
Miguel

Reputation: 1421

You can use the array methods next and key.

With next() you will move the array pointer one position. With key() you will get the key of the element of the array pointer. So the final code will be something like this:

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

next($age);
echo key($age);

Check it working here.

Upvotes: 3

Dung Tran
Dung Tran

Reputation: 118

I'd do something like this

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

$max = max($age); //get the highest age

foreach ($age as $key => $value) { //iterate through $age array
    if ($value == $max) {          //if the value is equal to max age 
        echo $key."<br />";        // then echo the key
    }
}

Upvotes: 3

Related Questions