Reputation: 35
How I could generate a list of numbers (18 numbers), which are in a range which starts with 1 and ends with 36 (including 1 and 36), and the generated numbers must be different from numbers which exist in an array.
Example: Array numbers: 27, 31, 18, 4, 15, 6
I need to output 18 random numbers which aren't in above array, and the numbers must not be duplicated.
Output I should get: 17, 21, 14, 28, 7, 8, 12, 20, 3, 5, 16, 2, 36, 11, 26, 13, 24, 35
function randomGen($min, $max, $quantity) {
$exluding_array = [1,2,3,4,5,6,7,8,9,10];
$numbers = range($min, $max);
shuffle($numbers);
if(range($min, $max) === $exluding_array) {
return "no";
} else {
return array_slice($numbers, 0, $quantity);
}
}
With this code I get random numbers without duplicates, but the returned numbers can be numbers from exluding_array
.
Upvotes: 0
Views: 69
Reputation: 14927
I would make use of array_filter
to filter out the excluded numbers:
function randomGen(int $min, int $max, int $quantity, array $excluded = []): array
{
$result = array_filter(range($min, $max), static function ($val) use ($excluded) {
return !in_array($val, $excluded, true);
});
shuffle($result);
return array_slice($result, 0, $quantity);
}
$result = randomGen(1, 36, 10, range(1, 10));
Demo: https://3v4l.org/nkbTK
Upvotes: 0
Reputation: 14255
You can use array_diff
to remove all numbers of excluding_array
from the generated numbers
before slicing:
function randomGen($min, $max, $quantity) {
$excluding_array = [1,2,3,4,5,6,7,8,9,10];
$numbers = range($min, $max);
// Remove unwanted numbers
$numbers = array_diff($numbers, $excluding_array);
shuffle($numbers);
if (count($numbers) < $quantity) {
return "no";
} else {
return array_slice($numbers, 0, $quantity);
}
}
Note: I also improved your sanity check a bit, although returning "no" doesn't seem to be the best solution in that case. You might want to throw an exception as shown by vivek_23.
Upvotes: 1
Reputation: 17805
Another approach is you can array_flip the $excluding array and check for these numbers existence in $numbers. If we find them, we skip them, else we include it in our final array.
We could also throw an Exception
if we can't produce as many numbers as $quantity
.
<?php
function randomGen($min, $max, $quantity) {
$exluding_array = [1,2,3,4,5,6,7,8,9,10];
$exluding_array = array_flip($exluding_array);
$numbers = range($min, $max);
shuffle($numbers);
$filtered_numbers = [];
foreach($numbers as $curr_number){
if(isset($exluding_array[$curr_number])) continue;
$filtered_numbers[] = $curr_number;
}
if(count($filtered_numbers) < $quantity) throw new Exception("Can't generate numbers with the given quantity and range.");
return array_slice($filtered_numbers, 0, $quantity);
}
print_r(randomGen(1,36,10));
Demo: https://3v4l.org/mUi8A
You can also make the callee of this function implement a try-catch block to handle the exception gracefully.
Upvotes: 0