John the Painter
John the Painter

Reputation: 2615

Randomly add 'items' or 'ads' into PHP loop

I have an events loop set up; and I also have an ads loop set up.

I want to inject each 'ad' into the events loop at random points. These loops/arrays have different set ups so can't push into the loop/array.

I had the below set up, which tended to work, but within ad.inc it was getting a random ad... whereas it should be getting the total count of ads and injecting them randomly into the events until that count is reached.

$count = 1;
$total = count($events);
$random = rand(3, $total);

foreach ($events as $event) {

    include('./inc/events-item.inc');

    if ($count == $random) {

        include("./inc/ad.inc");
        $random = rand($count, $total);

    }

    $count++;

}

For example, if my total events count is 30, and my total ads count is 4 then I should see the four ads randomly injected into the 30 events.

Any help?

Upvotes: 0

Views: 422

Answers (2)

u_mulder
u_mulder

Reputation: 54831

Create array of all positions for ads. If you have 30 ads - there're 30 positions, from 0 to 29:

$positions = range(0, 29);
// now get 4 random elements from this array:
$rand_positions = array_rand($positions, 4);
// though `array_rand` returns array of keys
// in this case keys are the same as values

// iterate over your events and if counter equals 
// to any value in $rand_positions - show ad
$i = 0;
foreach ($events as $event) {
    include('./inc/events-item.inc');
    if (in_array($i, $rand_positions, true)) {
        include("./inc/ad.inc");
    }
    $i++;
}

Upvotes: 3

Aurel Bílý
Aurel Bílý

Reputation: 7983

You need to randomly select 4 (or however many ads you have) points between 30 (or however many entries you have) other points. Here is a possible solution.

// Set up counts
$entry_count = count($events);
$ad_count = 4;

// Create an array of entry indices, and an array of ad indices
$entry_indices = range(0, $entry_count - 1);
$ad_indices = array();

// Fill the ad indices with random elements from the entry indices
for ($i = 0; $i < $ad_count; $i++) {
  $entry = rand(0, count($entry_indices));
  array_push($ad_indices, $entry_indices[$entry]);
  array_splice($entry_indices, $entry, 1);
}

// Sort it so we only need to look at the first element
sort($ad_indices);

// Iterate through the events
$count = 0;
foreach ($events as $event) {
  include('./inc/events-item.inc');
  // If we have any ad indices left, see if this entry is one of them
  if (count($ad_indices) > 0 && $count == $ad_indices[0]) {
    include("./inc/ad.inc");
    array_shift($ad_indices);
  }
  $count++;
}

Upvotes: 0

Related Questions