16

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--;
    }
?>
4
  • just to clear things up for you and avoid confusion. you have a multidimensional array of associative arrays. An object would be something like a class. Commented Nov 10, 2015 at 7:35
  • Thank for tha @iam-decoder
    – uno
    Commented Nov 10, 2015 at 7:39
  • You should not add the interget values as string, but as integer: array("Peter" => 35). Integers are faster than strings, use them where you can :)
    – Martijn
    Commented Nov 10, 2015 at 15:59
  • Ok . I will take note of that @Martijn . Thanks :)
    – uno
    Commented Nov 11, 2015 at 1:10

7 Answers 7

15

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; }));
11
  • your answer is fine the way it is. the only concern I can think is that they'd have to be using php 5.4+ to get this script to work with the immediate array access of a returned value on the last line :) Commented Nov 10, 2015 at 7:50
  • @iam-decoder you're right, I added a note about it! Commented Nov 10, 2015 at 7:51
  • Why don't you use ksort instead of uksort?
    – UpVs
    Commented Nov 10, 2015 at 7:59
  • 1
    This is a bad solution because you walk the array three times. It can be solved in only one iteration
    – Miguel
    Commented Nov 10, 2015 at 7:59
  • 1
    @MatteoTassinari Actually it uses the Quicksort algorithm under the hood and 'takes O(n log n) comparisons to sort n items. In the worst case, it makes O(n2) comparisons, though this behavior is rare.'
    – Tim
    Commented Nov 11, 2015 at 10:57
10

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
)
0
4

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"
4

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.

9
  • This is the best answer by my opinion, it runs in linear time complexity.
    – Tim
    Commented Nov 10, 2015 at 14:22
  • My solution using max() and array_filter() should still be O(n), so computationally equivalent to this one, isn't it? Commented Nov 10, 2015 at 15:14
  • @MatteoTassinari Computational complexity is not the same as performance. If an algorithm runs in O(n^2) for 100 items with each step taking 1ms that is 10 seconds. If it runs in O(n) for 100 items with each step taking 1 second that's 100 seconds. Which algorithm is better?
    – Tim B
    Commented Nov 10, 2015 at 15:43
  • 1
    @svrnm I appreciate your effort for the benchmark script. Maybe it is a good idea to expand it so that it becomes visible what scales and what does not scale, since the question of performance began with a discussion about scalability. :)
    – Tim
    Commented Nov 17, 2015 at 23:17
  • 1
    @Tim: I added some more details.
    – svrnm
    Commented Nov 18, 2015 at 15:11
3

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
    }
}
3

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.

1
1

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.

Not the answer you're looking for? Browse other questions tagged or ask your own question.