分配点数'基于位置的数组,如何处理关系?

时间:2013-08-12 17:13:36

标签: php

我有一个数组,其中包含一个带有名称的数组,然后是一个总量。然后根据总排名为该阵列分配“总分”。每个等级的积分减少2,但我的问题是如何处理关系?理想情况下,我会看到有多少关系,将这些排名的总积分相加,然后将它除以有多少关系,但我不知道如何真正实现这一点

这是我的数组:

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
}

将我的数组转换为:

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
        )

)

现在我正在做点什么来分配点数:

$maxpoints = 40;            
for($i = 0; $i < count($trainergross); $i++){
    $trainergross[$i]['points'] += $maxpoints;
    $maxpoints -=2;
}

现在我的数组看起来像这样:

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
        )

)

这是我的问题,有4个人“捆绑”但是得到了降低点,我不知道如何以我当前的代码设置的方式来解决这个问题。有人有任何指导吗?

2 个答案:

答案 0 :(得分:1)

您可以在迭代时存储最后一个已知值,并且只在值更改时减少点数。数组已排序,因此相等的元素将相邻。

/**
 * 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);

答案 1 :(得分:0)

您可以利用分数排序的事实;对于每次迭代,您尝试找到尽可能多的相等分数,然后一次更新整批:

$trainergross = [
    ['instr' => 'lee', 'gross' => 2094],
    ['instr' => 'steve', 'gross' => 1334],
    ['instr' => 'nick', 'gross' => 0],
    ['instr' => 'amber', 'gross' => 0],
    ['instr' => 'lindsay', 'gross' => 0],
];

$maxpoints = 40;

for ($current = 0; $current < count($trainergross); $current = $next) {
    // find the first unequal score and reduce points to calculate average later
    $next = $current; $minpoints = $maxpoints;
    while (++$next < count($trainergross) && $trainergross[$next]['gross'] == $trainergross[$current]['gross']) {
      $minpoints -= 2;
    }

    if ($minpoints == $maxpoints) {
        $trainergross[$current]['points'] = $maxpoints;
    } else {
        // tie, calculate average points to award
        $points = floor(($maxpoints + $minpoints) / 2);

        // update this batch
        for ($i = $current; $i < $next; ++$i) {
            $trainergross[$i]['points'] = $points;
        }
    }

    // decrease the points for next iteration
    $maxpoints = $minpoints - 2;
}

print_r($trainergross);