I have an array filled with arrays with a name, then a gross amount. This array is then being assigned a "points total" based on their gross ranking. The points decreases by 2 with every rank, but my issue is how can i deal with ties? Ideally i'd see how many ties, add up the total points for those rankings, then divide it by how many are tied, but i have no clue how to really accomplish that
Here is my array usort:
function grossSort($gross, $compare) {
if($gross['gross'] > $compare['gross'])
return -1; // move up
else if($gross['gross'] < $compare['gross'])
return 1; // move down
else
return 0; // do nothing
}
turns my array into this:
Array
(
[0] => Array
(
[instr] => lee
[gross] => 2094
)
[1] => Array
(
[instr] => steve
[gross] => 1334
)
[2] => Array
(
[instr] => nick
[gross] => 0
)
[3] => Array
(
[instr] => amber
[gross] => 0
)
[4] => Array
(
[instr] => lindsey
[gross] => 0
)
)
And here's what im doing to assign points now:
$maxpoints = 40;
for($i = 0; $i < count($trainergross); $i++){
$trainergross[$i]['points'] += $maxpoints;
$maxpoints -=2;
}
and now my array looks like this:
Array
(
[0] => Array
(
[instr] => lee
[gross] => 2094
[points] => 40
)
[1] => Array
(
[instr] => steve
[gross] => 1334
[points] => 38
)
[2] => Array
(
[instr] => nick
[gross] => 0
[points] => 36
)
[3] => Array
(
[instr] => amber
[gross] => 0
[points] => 34
)
[4] => Array
(
[instr] => lindsey
[gross] => 0
[points] => 32
)
)
And here's my issue, there are 4 people "tied" but getting decreasing points, I have no clue how to address this in the current way my code is set up. Anyone have any guidance?
You can store the last known value as you iterate, and only decrease the points when the value changed. The array is sorted, so the equal elements will be adjacent.
/**
* award average of points to a number of elements.
* @param arrayref $trainergross - reference to the original array
* @param int $award - total points to award
* @param int $start_index - which element to start with?
* @param int $count - how many elements should be awarded points?
* @return void
*/
function award_points(&$trainergross, $award, $start_index, $count=1)
{
if(!$count || $award<1) return; // if noone is waiting for the award, OR there is no award, bail out
// $awards holds total award, and we need to
$avgPoints = $award / $count;
// award points to $count previous elements
for($j = $start_index; $j < $start_index + $count; ++$j)
{
// in case points key was not initialized, php will issue a notice.
if(!isset($trainergross[$j]['points'])) $trainergross[$j]['points'] = 0;
$trainergross[$j]['points'] += $avgPoints;
}
}
/**
* This is increased on purpose
* the first check will be <some number> vs null, which will result in -=2.
* this is to eliminate additional !== null test inside the loop.
*/
$maxpoints = 42;
// This will be used to store number of consecutive elements
$count = 0;
// This will be used to store total points to award
$award = 0;
// Here we will store last gross value
$last = null;
for($i = 0; $i < count($trainergross); $i++)
{
$maxpoints -= 2;
// if gross has not changed, just count consecutive elements and continue
if($last == $trainergross[$i]['gross'])
{
$award += $maxpoints;
$count++;
continue;
}
// store gross value
$last = $trainergross[$i]['gross'];
// now really distribute the points we've gathered in award by now
award_points($trainergross, $award, $i - $count, $count);
// reset count back to 1 (there is only 1 "consecutive" element now)
$count = 1;
// next element will get this award
$award = $maxpoints;
}
// now we have to award points again
// the loop ended, but $count of elements are still awaiting points...
award_points($trainergross, $award, $i - $count, $count);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With