Brendan
Brendan

Reputation: 107

Need Three Highest Values (or more, if tied) of PHP Array and Their Location?

I have an array. I'd like to get the three highest values of the array, but also remember which part of the array it was in.

For example, if my array is [12,3,7,19,24], my result should be values 24,19,12, at locations 4, 0, 3.

How do I do that? The first part is easy. Getting the locations is difficult.

Secondly, I'd like to also use the top three OR top number after three, if some are tied. So, for example, if I have [18,18,17,17,4], I'd like to display 18, 18, 17, and 17, at location 0,1,2,3.

Does that make sense? Is there an easy way to do that?

Upvotes: 0

Views: 481

Answers (7)

mickmackusa
mickmackusa

Reputation: 47904

This task merely calls for a descending sort, retention of the top three values, and in the case of values after the third-positioned value being equal to the third value, retain these as well.

After calling rsort(), call a for() loop starting from the fourth element ([3]). If the current value is not equal to the value in the third position, stop iterating, and isolate the elements from the front of the array to the previous iteration's index. Done.

p.s. If the input array has 3 or fewer elements, the for() loop is never entered and the whole (short) array avoids truncation after being sorted.

Code: (Demo)

$array = [18, 17, 4, 18, 17, 16, 17];

rsort($array);

for ($i = 3, $count = count($array); $i < $count; ++$i) {
    if ($array[2] != $array[$i]) {
        $array = array_slice($array, 0, $i);
        break;
    }
}
var_export($array);

Because the loop purely finds the appropriate finishing point of the array ($i), this could also be compacted to: (Demo)

rsort($array);
for ($i = 3, $count = count($array); $i < $count && $array[2] === $array[$i]; ++$i);
var_export(array_slice($array, 0, $i));

Or slightly reduced further to: (Demo)

rsort($array);
for ($i = 3; isset($array[2], $array[$i]) && $array[2] === $array[$i]; ++$i);
var_export(array_slice($array, 0, $i));

Output:

array (
  0 => 18,
  1 => 18,
  2 => 17,
  3 => 17,
  4 => 17,
)

Upvotes: 0

Faesal
Faesal

Reputation: 823

try this:

public function getTopSortedThree(array $data, $n = 3, $asc = true)
{
    if ($asc) {
        uasort($data, function ($a, $b) { return $a>$b;});
    } else {
        uasort($data, function ($a, $b) { return $a<$b;});
    }
    $count = 0;
    $result = [];
    foreach ($data as $key => $value) {
        $result[] = $data[$key];
        $count++;
        if ($count >= $n){
            break;
        }
    }
    return $result;
}

Send false for desc order and nothing for asc order

Send $n with number of top values you want.

This functionality doesn't losing keys.

Upvotes: 0

trincot
trincot

Reputation: 350300

You can use a loop to determine how many elements your top-three-with-ties will have, after applying arsort:

function getTop($arr, $num = 3) {
    arsort($arr);
    foreach(array_values($arr) as $i => $v) {
        if ($i >= $num && $v !== $prev) return array_slice($arr, 0, $i, true);
        $prev = $v;
    }
    return $arr;
}

// Sample input
$arr = [4,18,17,6,17,18,9];
$top = getTop($arr, 3);
print_r($top); // [5 => 18, 1 => 18, 4 => 17, 2 => 17]

Upvotes: 0

coderodour
coderodour

Reputation: 1057

function top_three_positions($array){

  // Sort the array from max to min
  arsort($array);

  // Unset everything in  sorted array after the first three elements
  $count = 0;
  foreach($array as $key => $ar){
    if($count > 2){
       unset($array[$key]);
    }
    $count++;
  }

  // Return array with top 3 values with their indexes preserved.
  return $array;
}

Upvotes: 0

Adarsh Sojitra
Adarsh Sojitra

Reputation: 2199

This is what you need!

<?php
$array = array(12,3,7,19,24);
$array_processed = array();
$highest_index = 0;

while($highest_index < 3)
{
    $max = max($array);
    $index = array_search($max,$array);
    $array_processed[$index] = $max;
    unset($array[$index]);

    $highest_index++;
}

print_r($array_processed);
?>

You will get Index as well as the value! You just have to define how many top values you want! Let me know if it's what you want!

Upvotes: 0

quentino
quentino

Reputation: 1201

Or you can use arsort

function getMyTop($list, $offset, $top) {
    arsort($list);
    return array_slice($list, $offset, $top, true);
}

$myTop = getMyTop($list, 0, 3);
$myNextTop = getMyTop($list, 3, 4);

Upvotes: 0

Dygnus
Dygnus

Reputation: 641

Wouldn't you be there using asort()?

For example:

<?php
$list = [4,18,18,17,17];

// Sort maintaining indexes.
asort($list);

// Slice the first 3 elements from the array.
$top3 = array_slice($list, -3, null, true);

// Results in: [ 1 => 18, 2 => 18, 3 => 17 ]

Upvotes: 1

Related Questions