I have a sorted array (by value) with numbers from 900000 down to 000000 whilst the first digit describes a general positioning number, followed by all other digits.

The value gets a number based on previous calculations to form a filter score. The better the score, the higher the item that has this score will rank in general.

903402.55
^ ^  ^
| |  |_ Describes individual score in sorting -> higher -> better
| |__ describes general score value in sorting -> higher -> better
|__ describes general category that forms sorting roughly 

Now I have an array full of such scores, sorted by the score DESC (HIGH Scores to LOW Scores).

I.e.

[
'item_id_1' => 903402.55,
'item_id_2' => 903402.55,
'item_id_3' => 903402.52,
'item_id_4' => 903402.51,
'item_id_5' => 903402.40,
'item_id_6' => 903402.39,
'item_id_7' => 903402.37,
'item_id_8' => 903402.37,
'item_id_9' => 903402.21,
'item_id_10' => 903402.10,
'item_id_11' => 903402.08,
'item_id_12' => 903402.01,
]

and so on.

Now I want to shuffle every 3rd item, but maintain general order, so that the fourth item cannot become the second item of the whole array, but withing position 1-3, respectively scaled upon processing the whole array.

Meaning that my potential outcome would like this:

[
'item_id_3' => "now better then 1",
'item_id_1' => "now worse then 3 but better then 2",
'item_id_2' => "now worse then 1 but better then 5",
'item_id_5' => "now better then 4, can't change 3-group",
'item_id_4' => "now worse then 5",
'item_id_6' => "now worse then 4",
...
]

What I have done is to group the whole array by 3, so that I get an array that contains each 3 elements in the correct order.

$i = 0;
        $shuffleGroup = [];
        foreach ($scores as $productId => $score) {
            $shuffleGroup[$i][$productId] = $score;
            if(count($shuffleGroup[$i]) === 3){
                $i++;
            }
        }

Now I'd like to create a proper manipulation of the score to keep general order but randomize by a chunk of 3.

How would I do that?

1 Answers

0
Nigel Ren On

From what I understand, this code first splits the scores into chunks of 3.

Then to potentially change the order it first fetches the highest and lowest score in that group and then assigns a new random number (between the min and max, rounded to 2 decimal places) to each of the 3 items in the group (Random number generated using algorithm from the examples in the manual).

Then reassembles the whole array and uses arsort() to sort the result by the random scores...

$groups = array_chunk($scores, 3, true);
foreach($groups AS &$group) {
    $min = min($group);
    $max = max($group);
    foreach ( $group as &$score )    {
        $score = round($min + mt_rand() / mt_getrandmax() * ($max - $min),2);
    }
}
$newScores = array_merge(...$groups);
arsort($newScores);