Reputation: 1
I'm creating a php file that displays 4 event sponsor ads. For each sponsor I created an element in an array for their id, name, URL to site, URL for image, level of sponsor, value of sponsorship
I want to create a randomizer that will randomly populate 4 records from the array, but weight the values so that higher level sponsors appear more often than others. I've already created the value for the weight as a percent.
The closest solution I've found to this problem is:
MySQL: Select Random Entry, but Weight Towards Certain Entries
Which suggests including this code, BUT the referenced link for the similar issue doesn't make sense to me. It suggests using ORDER BY -LOG(1.0 – RAND()) / Multiplier
but I'm using an array, not record results and I'm not completely clear on how this works...
It looks like array_rand will be helpful to at least generate the 4 different values, but still not sure how to weight them.
Upvotes: 0
Views: 446
Reputation: 1
OK, I finally worked everything out!
Here is how my final code went (I've separated and simplified the code here to piece-meal the tasks):
Create the array
$Sponsors=array( array('Sponsor' => 'Sponsor1', 'Value' => '500'), array('Sponsor' => 'Sponsor2', 'Value' => '300'), array('Sponsor' => 'Sponsor3', 'Value' => '300'), array('Sponsor' => 'Sponsor4', 'Value' => '200'),) );
Set SponsorTotalCt = the number of sponsors and create a variable to hold the weighted percentage
$SponsorTotalCt = count($Sponsors);
$SponsorWeight = 0;
Get a total value for all the sponsorships
$SponsorTotalAmt = 0; foreach($Sponsors as $array) { $SponsorTotalAmt += $array['Value']; };
Add the sponsor weight as a percent as another 'field value' in the $Sponsors array
$i = 0; //initialize i while ($i < $SponsorTotalCt){ foreach($Sponsors as $array) { $SponsorWeight = round($Sponsors[$i]['Value']/$SponsorTotalAmt * 100); $Sponsors[$i]['Weight'] = $SponsorWeight; }; $i++; // count one up };
*Note: at this point the $Sponsors 'record listing' would look kind of like this
$Sponsors =
[0] 'Sponsor1','500', 38 (this last is the percent the sponsorship should be weighted)
[1] 'Sponsor2', '300', 23
[2] 'Sponsor3', '300', 23
[3] 'Sponsor4', '200', 15
Notice that the last set of values adds up to 100, or close to it (because of the rounding)*
Create a new array of 100 'records' where each row of the $Sponsors array is repeated the number of times that reflects the percentage. i.e. Sponsor1 values will be repeated in the array 38 times
$newSponsors = array(); $i = 0; //initialize i while ($i < $SponsorTotalCt){ foreach($Sponsors as $array) { $a = array_fill(0, $Sponsors[$i]['Weight'], $Sponsors[$i]);
}; $newSponsors= array_merge($newSponsors,$a); $i++; // count one up };
Finally, randomly select 3 keys from the 4 Sponsors, weighted by the value of their Sponsorships
$spot = array_rand($newSponsors,3);
Now I only have to create the code and call the value. YAY!
Upvotes: 0
Reputation: 1826
You may use a custom function to sort the array based on the weight of sponsor. See usort
.
usort($data, function ($value) {
return rand(0, 100 - $value['weight']);
});
Example:
$data = array(
array('name' => 'low', 'weight' => 5),
array('name' => 'medium', 'weight' => 35),
array('name' => 'high', 'weight' => 60)
);
$frequency = array();
for ($i = 0; $i < 1000; $i++) {
usort($data, function ($value) {
return rand(0, 100 - $value['weight']);
});
$head = reset($data);
if (!isset($frequency[$head['name']])) {
$frequency[$head['name']] = 0;
}
$frequency[$head['name']]++;
}
print_r($frequency);
/*
Array
(
[low] => 263
[medium] => 328
[high] => 409
)
*/
Upvotes: 3
Reputation: 25279
This ORDER BY
statement will not be executed by your application, it rather tells the DBMS to order the results returned by your query. You add a LIMIT 4
to the query and you're set.
EDIT Oh, I just read that you do not use a database.
EDIT 2 To really answer your question:
Upvotes: 0