markb
markb

Reputation: 1295

Avoid duplicate outputs on array_rand loop

I am trying to loop through an array for a max amount of times in a loop, but I'm trying to figure out how to have it not output the same set twice.

Below is the crux of the code, stripping out all the superfluous code.

Previously when I looked at this code it had an unset() which I have commented out. I don't think it was doing what it is supposed to, and I really can't think of a way to stop it without adding an id to the individual arrays.

I have built this dummy array:

$array = array(
    array(
        'title'     =>  'Bill',
        'url'       =>  'example.com/?u=1',
        'img'       =>  'image1.jpg'
    ),
    array(
        'title'     =>  'Frank',
        'url'       =>  'example.com/?u=2',
        'img'       =>  'image1.jpg'
    ),
    array(
        'title'     =>  'Jill',
        'url'       =>  'example.com/?u=3',
        'img'       =>  'image1.jpg'
    )
    ...
);

and I have the output page:

$a = 0;
$m = 2; // output max two set via $max

foreach( $users as $user ) {

    $a++;
    // unset( $users[$random_out] );

    if( $a < $m ) {

        $random_out = array_rand( $users );
        $user_title = $users[$random_out]['title'];
        $user_url    = $users[$random_out]['url'];
        $user_img    = $users[$random_outid]['img'];

        echo '<a href="' . $user_url . '">';
            echo '<img src="' . $user_img . '">';
            echo $user_title;
        echo '</a>';
    }

}

Upvotes: 0

Views: 332

Answers (3)

Nick
Nick

Reputation: 147166

You can just use the second parameter ($num) of array_rand to achieve your result. if $num is specified, array_rand will return an array of random keys.

foreach (array_rand($users, $m) as $random_out);
    $user_title  = $users[$random_out]['title'];
    $user_url    = $users[$random_out]['url'];
    $user_img    = $users[$random_outid]['img'];

    echo '<a href="' . $user_url . '">';
    echo '<img src="' . $user_img . '">';
    echo $user_title;
    echo '</a>';
}

Upvotes: 1

Scuzzy
Scuzzy

Reputation: 12332

As pointed out by @Sammitch, shuffle + array_slice is a much simpler solution. If you don't want the original array shuffled, make a copy of it.

// Shuffle the Array
shuffle( $users );
// Loop over the first two items from the array
foreach( array_slice( $users, 0, 2 ) as $user )
{
  echo '<a href="' . $user['url'] . '">';
  echo '<img src="' . $user['img'] . '">';
  echo $user['title'];
  echo '</a>';
}

This function will select $limit number of unique items from your array pool

$array = array('cat','dog','hamster','elephant','otter');

function random_unique_items_from_array( $array, $limit = 1 )
{
  $history = array();
  $result = array();
  while( count( $result ) < $limit and count( $history ) < count( $array ) )
  {
    if( in_array( $randKey = array_rand( $array ), $history ) === false )
    {
      $history[] = $randKey;
      $result[ $randKey ] = $array[ $randKey ];
    }
  }
  return $result;
}

var_dump( random_unique_items_from_array( $array, 2 ) );
var_dump( random_unique_items_from_array( $array, 5 ) );
var_dump( random_unique_items_from_array( $array, 500 ) );

So now instead of keeping track during the loop just do this

foreach( random_unique_items_from_array( $users, 2 ) as $user )
{
  echo '<a href="' . $user['url'] . '">';
  echo '<img src="' . $user['img'] . '">';
  echo $user['title'];
  echo '</a>';
}

Upvotes: 0

Simon R
Simon R

Reputation: 3772

You could do something like this if you just want unique users;

<?php

$array = array(
    array(
        'title'     =>  'Bill',
        'url'       =>  'example.com/?u=1',
        'img'       =>  'image1.jpg'
    ),
    array(
        'title'     =>  'Frank',
        'url'       =>  'example.com/?u=2',
        'img'       =>  'image1.jpg'
    ),
    array(
        'title'     =>  'Jill',
        'url'       =>  'example.com/?u=3',
        'img'       =>  'image1.jpg'
    )
);

//set the number of random users you want
$totalNumberOfRandomUsers = 2;

// loop over the number of random users you want
for($i = 1; $i <= $totalNumberOfRandomUsers; $i++) {
    // get a random number between 0 and the count of the array - 1 
    // as arrays are zero indexed
    $rand = rand(0,count($array)-1);
    // get the nth index of the array and assign it to a users array
    $users[] = $array[$rand];
    // unset the index you've just added and 'reset' the array
    // so that there are no missing indexes
    unset($array[$rand]);
    $array = array_values($array);
}

// die and dump the users array.
die(var_dump($users));

Upvotes: 0

Related Questions