Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

get random value from a PHP array, but make it unique

Tags:

arrays

php

random

I want to select a random value from a array, but keep it unique as long as possible.

For example if I'm selecting a value 4 times from a array of 4 elements, the selected value should be random, but different every time.

If I'm selecting it 10 times from the same array of 4 elements, then obviously some values will be duplicated.

I have this right now, but I still get duplicate values, even if the loop is running 4 times:

$arr = $arr_history = ('abc', 'def', 'xyz', 'qqq');

for($i = 1; $i < 5; $i++){
  if(empty($arr_history)) $arr_history = $arr; 
  $selected = $arr_history[array_rand($arr_history, 1)];  
  unset($arr_history[$selected]); 
  // do something with $selected here...
}
like image 758
Alex Avatar asked Jun 24 '11 17:06

Alex


8 Answers

You almost have it right. The problem was the unset($arr_history[$selected]); line. The value of $selected isn't a key but in fact a value so the unset wouldn't work.

To keep it the same as what you have up there:

<?php

$arr = $arr_history = array('abc', 'def', 'xyz', 'qqq');

for ( $i = 1; $i < 10; $i++ )
{
  // If the history array is empty, re-populate it.
  if ( empty($arr_history) )
    $arr_history = $arr;

  // Select a random key.
  $key = array_rand($arr_history, 1);

  // Save the record in $selected.
  $selected = $arr_history[$key];

  // Remove the key/pair from the array.
  unset($arr_history[$key]);

  // Echo the selected value.
  echo $selected . PHP_EOL;
}

Or an example with a few less lines:

<?php

$arr = $arr_history = array('abc', 'def', 'xyz', 'qqq');

for ( $i = 1; $i < 10; $i++ )
{
  // If the history array is empty, re-populate it.
  if ( empty($arr_history) )
    $arr_history = $arr;

  // Randomize the array.
  array_rand($arr_history);

  // Select the last value from the array.
  $selected = array_pop($arr_history);

  // Echo the selected value.
  echo $selected . PHP_EOL;
}
like image 75
Francois Deschenes Avatar answered Oct 01 '22 06:10

Francois Deschenes


How about shuffling the array, and popping items off.

When pop returns null, reset the array.

$orig = array(..);
$temp = $orig;
shuffle( $temp );

function getNextValue()
{
  global $orig;
  global $temp;

  $val = array_pop( $temp );

  if (is_null($val))
  {
    $temp = $orig;
    shuffle( $temp );
    $val = getNextValue();
  }
  return $val;
}

Of course, you'll want to encapsulate this better, and do better checking, and other such things.

like image 37
zzzzBov Avatar answered Oct 02 '22 06:10

zzzzBov


http://codepad.org/sBMEsXJ1

<?php

    $array = array('abc', 'def', 'xyz', 'qqq');

    $numRandoms = 3;

    $final = array();

    $count = count($array);

    if ($count >= $numRandoms) {

        while (count($final) < $numRandoms) {

            $random = $array[rand(0, $count - 1)];

            if (!in_array($random, $final)) {

                array_push($final, $random);
            }
        }
    }

    var_dump($final);

?>
like image 45
Steve Robbins Avatar answered Sep 29 '22 06:09

Steve Robbins


Php has a native function called shuffle which you could use to randomly order the elements in the array. So what about this?

$arr = ('abc', 'def', 'xyz', 'qqq');

$random = shuffle($arr);

foreach($random as $number) {
    echo $number;
}
like image 32
KingOfCode Avatar answered Oct 03 '22 06:10

KingOfCode


key != value, use this:

$index = array_rand($arr_history, 1);
$selected = $arr_history[$index];  
unset($arr_history[$index]); 
like image 43
Karoly Horvath Avatar answered Oct 01 '22 06:10

Karoly Horvath


I've done this to create a random 8 digit password for users:

$characters = array(
    "A","B","C","D","E","F","G","H","J","K","L","M",
    "N","P","Q","R","S","T","U","V","W","X","Y","Z",
    "a","b","c","d","e","f","g","h","i","j","k","m",
    "n","p","q","r","s","t","u","v","w","x","y","z",
    "1","2","3","4","5","6","7","8","9");

for( $i=0;$i<=8;++$i ){
    shuffle( $characters );
    $new_pass .= $characters[0];
}
like image 23
sadmicrowave Avatar answered Oct 03 '22 06:10

sadmicrowave


If you do not care about what particular values are in the array, you could try to implement a Linear Congruential Generator to generate all the values in the array.

LCG implementation

Wikipedia lists some values you can use, and the rules to select the values for the LCG algorithm, because the LCG algorith is deterministic it is guaranteed not to repeat a single value before the length of the period.

After filling the array with this unique numbers, you can simply get the numbers in the array 1 by 1 in order.

like image 44
Oscar Gomez Avatar answered Oct 01 '22 06:10

Oscar Gomez


$isShowCategory = array();
for ($i=0; $i <5 ; $i++) { 
   $myCategory = array_rand($arrTrCategoryApp,1); 
   if (!in_array($myCategory, $isShowCategory)) {
      $isShowCategory[] = $myCategory;

      #do something 

   }
}
like image 33
lookly Dev Avatar answered Oct 01 '22 06:10

lookly Dev