Reputation: 1754
I know how to select one random item from an array, but how about ten random items from an array of, say, twenty items? (In PHP.)
What makes it a little more complicated is that each item actually has two parts: a filename, and a description. Basically, it's for a webpage that will display ten random images each time you reload. The actual format of this data doesn't really matter, although it's simple enough that I'd prefer to contain it in flat-text or even hard code it rather than set up a database. (It's also not meant to change often.)
Upvotes: 12
Views: 9660
Reputation: 47894
If you don't want to shuffle()
the entire array (perhaps because your array is relatively large), you can call array_rand()
to populate an array of keys then filter the input array using that array of keys.
Code: (Demo)
$input = [
['filename' => 'a.php', 'description' => 'foo'],
['filename' => 'b.php', 'description' => 'fooey'],
['filename' => 'c.php', 'description' => 'bar'],
['filename' => 'd.php', 'description' => 'berry'],
['filename' => 'e.php', 'description' => 'buoy'],
['filename' => 'f.php', 'description' => 'barf'],
['filename' => 'g.php', 'description' => 'food'],
['filename' => 'h.php', 'description' => 'foodie'],
['filename' => 'i.php', 'description' => 'boof'],
['filename' => 'j.php', 'description' => 'boogey'],
['filename' => 'k.php', 'description' => 'fudge'],
['filename' => 'l.php', 'description' => 'fudgey'],
['filename' => 'm.php', 'description' => 'barge'],
['filename' => 'n.php', 'description' => 'buggy'],
['filename' => 'o.php', 'description' => 'booger'],
['filename' => 'p.php', 'description' => 'foobar'],
['filename' => 'q.php', 'description' => 'fubar'],
['filename' => 'r.php', 'description' => 'goof'],
['filename' => 's.php', 'description' => 'goofey'],
['filename' => 't.php', 'description' => 'boofey'],
];
var_export(
array_intersect_key(
$input,
array_flip(
array_rand($input, 10)
)
)
);
The output, you will notice, has only 10 rows of randomly selected data in it.
Different from shuffle()
, because $input
is nominated first in array_intersect_key()
, the "random" items are actually in their original order.
Even if you iterate array_rand()
's returned array with a classic loop, the results will still be ordered by their position in the original array.
Code: (Demo)
$randoms = [];
foreach (array_rand($input, 10) as $key) {
$randoms[] = $input[$key];
}
var_export($randoms);
If the position of the random elements is important, you should call shuffle()
on the randomly selected results.
Note that the PHP manual says the following for array_rand()
:
[array_rand()] uses a pseudo random number generator that is not suitable for cryptographic purposes.
When picking only one entry, array_rand() returns the key for a random entry. Otherwise, an array of keys for the random entries is returned. This is done so that random keys can be picked from the array as well as random values.
If multiple keys are returned, they will be returned in the order they were present in the original array.
Trying to pick more elements than there are in the array will result in an E_WARNING level error, and NULL will be returned.
If you aren't sure how many random items will be selected or how many items are in the array, then use min($yourNumberOfRandomItemsToReturn, count($yourArray))
.
Upvotes: 1
Reputation: 5558
You can select one or more random items from an array using array_rand()
function.
Upvotes: 15
Reputation: 4685
I have some code that sort of does what you ask for. I store a list of sponsorship links in a text file, and pick them at random. But, if I want to skew the set, I use multiple the links ;-)
Sponsors file:
<a href="http://www.example.com">Example</a>
<a href="http://www.example.com">Example</a>
<a href="http://www.bbc.co.uk">BBC</a>
<a href="http://www.google.com">Google</a>
PHP:
$sponsor_config = 'sponsors.txt';
$trimmed = file($sponsor_config, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$op = array();
$limit = 20; // insurance
$loops = 0;
$needed = 4;
$op[] = '<div id="sponsorship"><!-- start sponsorship -->';
$selected = array();
while ( (count($selected) < $needed) AND ($loops <= $limit)) {
$choice = rand(0, count($sponsors)-1);
if(!in_array($sponsors[$choice], $selected)) $selected[] = $sponsors[$choice];
$loops++;
}
foreach($selected as $k => $selection) {
$op[] = '<p class="sponsorship bg_'.($k%3+1).'">Click the link below to<br />visit our Site Sponsor:<br />'.$selection.'</p>';
}
$op[] = '</div><!-- end sponsorship -->';
return join("\n",$op)."\n";
V. quick and v.v. dirty... but it works
Upvotes: 0
Reputation: 3843
An array of arrays in PHP should be a good strategy. You can keep the data for these array in any way you like (hard-coded, XML, etc) and arrange it in the arrays as such:
Array {
Array (item0) { filename,description, weight,...}
Array (item1) { filename,description, weight,...}
Array (item2) { filename,description, weight,...}
}
You can then use the array_rand function to randomly remove items from the array. Creating a weight value for each entry will allow you to pick one entry over another using some sort of priority strategy (e.g. randomly get 2 items from the array, check weight, pick the one with a greater weight and replace the other)
Upvotes: 0
Reputation: 655239
You could shuffle
the array and then pick the first ten elements with array_slice
:
shuffle($array);
$tenRandomElements = array_slice($array, 0, 10);
Upvotes: 26