How to get random value from array set an value in array that will be one to selected more than other?
array('00','01','02');
I want to select an random value from this array with most selected value be '00', i.e the '00' value will be selected 80% and other two values will be 20%.
Here array can have many values, its only an example with three values
$main_array=array('00','01','02');
$priority=array(0,0,0,0,0,0,0,0,1,2);
$rand_index=array_rand($priority);//select a random index from priority array.. $priority[$rand_index] will give you index 0 or 1 or 2 with your priority set..
echo $main_array[$priority[$rand_index]];
I think the code is self explanatory...
Array will have many elements case will come when lets say the requirement will come like 3% probability of "00" 28% prob. of "01" rest to other elements...In that case use array_fill function to fill elements in masses...and array_merge them
Like for the same case I've taken answer will be
$main_array=array('00','01','02');
$priority1=array_fill(0,69,2);
$priority2=array_fill(0,28,1);
$priority3=array_fill(0,3,0);
$priority=array_merge($priority1,$priority2,$priority3);
$rand_index=array_rand($priority);
echo $main_array[$priority[$rand_index]];
Here's an idea.
$arr = array('00', '01', '02');
$randInt = rand(1, 10);
if ($randInt <= 8) {
$value = $arr[0];
}
else if ($randInt == 9) {
$value = $arr[1];
}
else { // ($randInt == 10)
$value = $arr[2];
}
There is now an 80% chance that $value contains '00', a 10% chance that it contains '01', and a 10% chance it contains '02'. This may not be the most efficient solution, but it will work.
one of many options
$a = array_fill(0, 8, '0');
$a['9']='1';
$a['10']='2';
echo $a[array_rand($a,1)];
Use a parallel array with the probability distribution, e.g.:
array('80', '10', '10');
Use standard random number function to generate a number between 0 and 99, then look it up in this array. The index you find it at is then used as the index to the values array.
Related
I am trying to figure out how to count a number that I pull from query string and push each into an array. so if the number is 3, I want to push 1, 2 and 3 as separate numbers into the array. The below code does not work:
$number = $_GET['tics'];
$items = array();
for($numbers = 0; $numbers<$number; $numbers++) {
$items[] = $numbers;
}
var_dump shows an empty array with this code. any idea how to make this work?
I want the key to be "numbers" and the values to be 1, 2, 3 etc..
I am sure this is explained many times already on stack, but when searching I found only examples that was way to advanced for someone like me
you can use range()
Returns an array of elements from start to end, inclusive.
$number = (int) $_GET['tics'];
$items = range(1, $number);
You can use http://php.net/manual/en/function.range.php to generate a list of numbers from min to max.
<?php
$number = 5;
// Do validation on $number before passing it to range.
$result = range(1, $number);
print_r($result);
For starters, your loop is incorrect.
If you pass $number = 3
for ($numbers = 0; $numbers < $number; $numbers++) {
Will give you 0, 1, 2. You need to change it to the following:
for ($numbers = 1; $numbers <= $number; $numbers++) {
This will give you 1, 2, 3.
Anyway, entertaining another idea here, if range() as mentioned by the other answers is not what you require.
I want the key to be "numbers" and the values to be 1, 2, 3 etc..
It's not exactly clear what you mean by this, but I'm guessing you might want the array keys to be the value of $numbers? In which case, you can modify your code as follows:
$number = (int)$_GET['tics'];
$items = array();
for ($numbers = 1; $numbers <= $number; $numbers++) {
$items[$numbers] = $numbers;
}
Your code should somewhat work as intended anyway (the numbers will be incorrect). The reason it doesn't is probably that $_GET['tics'] has no value. Ensure that you do indeed have tics in the $_GET array, and that you aren't actually POSTing (in which case you need $_POST['tics'] instead).
If you change $_GET in your code to $_POST and it still doesn't work, then tics is either not set or does not have a value greater than 0.
I'm trying to create a random number generator in PHP. It's supposed to generate three (3) numbers at a time, without repeat. That's to say, the 3 numbers cannot be the same.
Here's what I've tried so far:
$array = [];
$A = mt_rand(1,36);
$array[0] = $A;
$B = mt_rand(1,36);
$array[1] = $B;
if(in_array($B,$array)){
$B = mt_rand(1,36);
$array[1] = $B;
}
$C = mt_rand(1,36);
$array[2] = $C;
if(in_array($C,$array)){
$C = mt_rand(1,36);
$array[2] = $C;
}
$length = count($array);
//display the array values;
for($i = 0; $i < $length; $i++){
echo ($array[$i]."<br>");
}
Can anyone tell me where I'm going wrong?
Like this ( as per my initial comment ),
$array = [];
while( count($array) < 3 ){
$rand = mt_rand(1,36);
$array[$rand] = $rand;
}
print_r( $array );
By setting the "key" to be the random number, we can abuse the fact that associative array keys are unique. Then it's a simple matter of waiting until the array contains the desired amount of unique items.
You can test it here
Outputs: ( your results may vary, it's random )
Array
(
[16] => 16
[20] => 20
[27] => 27
)
UPDATE I was trying to think of a valid way to do it without using a loop ( on my way home from work ), and this way may be even better in some cases.
$a = range(1,36);
shuffle($a);
$array = array_slice($a, 0, 3);
print_r($array);
This will have better performance when the number of items you must find is higher. This is because there is no repetition, no collisions. So if you have a small range but need to find many items for the return, this will preform better. If you have many items and need to return only few, then the first one may be better, if not from speed then from memory use.
You can see it here
For reference this uses
range() - Create an array containing a range of elements.
http://php.net/manual/en/function.range.php
shuffle() - Shuffles (randomizes the order of the elements in) an array. It uses a pseudo random number generator that is not suitable for cryptographic purposes.
http://php.net/manual/en/function.shuffle.php
array_slice() - Returns the sequence of elements from the array as specified by the offset and length parameters.
http://php.net/manual/en/function.array-slice.php
So to explain this last one
First we create an array that contains each of our possible numbers as an element. So for example like this [1,2,3,4,5,6, ...].
Next we shuffle it which randomizes the order of the whole array. Shuffle modifies the array by "reference" so it doesn't return our array and therefor there is no assignment ( I think it returns Boolean, however I'm at a loss as to how it could fail and return false, pretty much it just returns true which we don't want to overwrite our array with ). So our example then becomes this [16,20,27,14,5,1, ...]
Last we cut out the number of items we need to return. Finally we end the example with this [16,20,27];
You can crunch the first one down into one ( really 2) line by assigning the value of the $rand variable in the condition of the loop. Like this:
$array = [];
while( count($array) < 3 && false !== ($rand = mt_rand(1,36))) $array[$rand] = $rand;
Because mt_rand(1,36) will never return boolan false. Also if I remember mt_rand is the same as rand now, or at least in current PHP versions.
Note: As of PHP 7.1.0, rand() uses the same random number generator as mt_rand(). To preserve backwards compatibility rand() allows max to be smaller than min as opposed to returning FALSE as mt_rand(). http://php.net/manual/en/function.rand.php
Hope it helps you, remember to think outside of the box.
$arr = array(
1, 1, 2, 3, 4
);
How to find out the pair from this array ?
Keep in mind that the pair from array could be any number (1,2,4,3,2) or (3,3,1,2,4); I just give an random example above.
if there is a pair in array
echo "The pair number is 1";
All of my methods will return the desired result as long as there IS a duplicate. It is also assumed because of your sample input, that there is only 1 duplicate in the array. The difference between my methods (and the other answers on this page) will be milliseconds at most for your input size. Because your users will not be able to distinguish between any of the correct methods on this page, I will suggest that the method that you implement should be determined by "readability","simplicity", and/or "brevity". There are many coders who always default to for/foreach/while loops. There are others who always defer to functional iterators. Your choice will probably just come to down to "your coding style".
Input:
$arr=[1,1,2,3,4];
Method #1: array_count_values(), arsort(), key()
$result=array_count_values($arr);
arsort($result); // this doesn't return an array, so cannot be nested
echo key($result);
// if no duplicate, this will return the first value from the input array
Explanation: generate new array of value occurrences, sort new array by occurrences from highest to lowest, return the key.
Method #2: array_count_values(), array_filter(), key()
echo key(array_filter(array_count_values($arr),function($v){return $v!=1;}));
// if no duplicate, this will return null
Explanation: generate the array of value occurrences, filter out the 1's, return the lone key.
Method #3: array_unique(), array_diff_key(), current()
echo current(array_diff_key($arr,array_unique($arr)));
// if no duplicate, this will return false
Explanation: remove duplicates and preserve the keys, find element that went missing, return the lone value.
Further consideration after reading: https://www.exakat.io/avoid-array_unique/ and the accepted answer from array_unique vs array_flip I have a new favorite 2-function one-liner...
Method #4: array_count_values(), array_flip()
echo array_flip(array_count_values($arr))[2];
// if no duplicate, this will show a notice because it is trying to access a non-existent element
// you can use a suppressor '#' like this:
// echo #array_flip(array_count_values($arr))[2];
// this will return null on no duplicate
Explanation: count the occurrences (which makes keys of the values), swap the keys and values (creating a 2-element array), access the 2 key without a function call. Quick-smart!
If you wanted to implement Method #4, you can write something like this:(demo)
$dupe=#array_flip(array_count_values($arr))[2];
if($dupe!==null){
echo "The pair number is $dupe";
}else{
echo "There were no pairs";
}
There will be many ways to achieve your desired result as you can see from all of the answers, but I'll stop here.
First sort your array, then use foreach loop and if current and next are equal and not echo this item before this time, echo item is pair.
$arr = array(
1, 3, 1, 2, 2, 2, 3, 4
);
sort($arr);
$last_number = null;
foreach($arr as $key => $item) {
if(array_key_exists($key + 1, $arr)) {
if($item === $arr[$key + 1]) {
if($last_number !== $item) {//prevent duplicate echo pair of one item
echo 'The pair number is ' . $item;
$last_number = $item;
}
}
}
}
Use built-in array_count_values. Then iterate over results and check if count is greater than 1.
$arr = array(
1, 1, 2, 3, 4
);
$values = array_count_values($arr);
foreach ($values as $key => $value) {
if ($value > 1) {
echo 'Pair: ' . $key;
// break, if you need to show first pair only
// break;
}
}
You can first count all the values in the array, then for each distinct value check if it occurs twice in the array.
<?php
$array = array(1, 1, 2, 3, 4);
$vars = array_count_values($array);
foreach($vars as $key => $var) {
if($var == 2) {
echo "The pair number is " . $key . "<br>";
}
}
?>
First sort the array, then check if there are two numbers on consecutive indexes with the same value.
This is the most efficient solution: sorting is done in O(n log n) time1 and doing the checking takes O(n) time. Overall, you'll have the answer in O(n log n) time. Naive approaches will use O(n2) time.
If you don't want to modify the original array, do all of the above on a copy.
function hasEqualPair($arr) {
sort($arr);
$l = count($arr);
for ($i = 1; $i < $l; ++$i) {
if ($arr[$i] === $arr[$i - 1]) {
return true;
}
}
return false;
}
var_dump(hasEqualPair(array(1, 2, 4, 3, 2))); // true
var_dump(hasEqualPair(array(1, 1, 2, 3, 4))); // true
var_dump(hasEqualPair(array(3, 3, 1, 2, 4))); // true
var_dump(hasEqualPair(array(3, 5, 1, 2, 4))); // false
Try it online!
Of course, if you want to know what the pair is, just change return true in the above function to return $arr[$i]. You then might want to change the function name to getEqualPair as well.
1 The sort function in PHP uses Quicksort. It is possible to make that always run in O(n log n) time, but the implementation in PHP probably has an average running time of O(n log n), with worst case running time still O(n2).
$arr = array(
1, 1, 2, 3, 4
);
echo "<pre>";
$vals = array_count_values($arr);
foreach ($vals as $key => $value) {
if($value%2==0){
echo "The pair number is ".$key."<br>";
}else{
echo "The not pair number is ".$key."<br>";
}
}
Basically I wondering the best approach to determine a score based on a range defined in an array
I have a set of values ranging between 300 and 900 , each value has a corresponding percentile range.
I want to create a function that gives you the percentile based on the value checked. The value passed into the function may not match the defined value in the array, but want to return the highest percentile for that value.
For example in the array will be something like
'300'=>'10', '333'=>'11', '340' => '12' .... '900'=>'100'
IF I pass in 335, then the function should return 11. Not sure simplest approach.
You can easly loop .. but if you don't want to do that then you can use
$var = 335 ;
$array = array('300'=>'10', '333'=>'11', '340' => '12');
echo getPercentage($array,$var);
Output
11
Function Used
function getPercentage(array $a, $v) {
if (array_key_exists($v, $a)) {
return $a[$v];
}
$a[$v] = null;
ksort($a);
$pos = array_search($v, array_keys($a));
$pos = array_slice($a, (($pos == 0) ? 1 : $pos - 1), 1);
return reset($pos);
}
If the array is ordered, it's straightforward. If you start at the bottom (score = 300) then go up until your score is larger than the array score, and the correct percentile is the one you just passed on the way up. If you start at the top, go down until your score is lower than the array score, and the correct percentile is the one you just passed on the way down.
Starting at the top or bottom of your array based on the score may give you a slight performance gain.
You can do it this way:
<?php
function get_percentile($val){
$arr = array('300'=>'10', '333'=>'11', '340'=>'12');
while(!$arr[$val]){
$val--;
}
return $arr[$val];
}
echo get_percentile(335);
?>
Output:
11
Check it out!
I am wondering how I can drop any array items that come after a certain number like 6. Is there something in PHP that enables you do do it? Or is it a custom function that needs to be written
You could use array_slice for this purpose. For example:
$testArray = range(0, 10);
// Ensure there are at least six items in the source array.
if(count($testArray) >= 6) {
// Grab the first six items.
$firstSixItemsFromArray = array_slice($testArray, 0, 6);
}
If you're looking to take the first six elements of an array, based on position in the array, then array_slice or array_splice is the way to go.
array_splice($array, 6);
If you want to keep all elements with value less than 6, you could do something like:
$array = array_filter($array, function($v) { return $v <= 6; });