【问题标题】:get random value from a PHP array, but make it unique从 PHP 数组中获取随机值,但使其唯一
【发布时间】:2011-09-22 05:21:04
【问题描述】:

我想从数组中选择一个随机值,但要尽可能保持唯一。

例如,如果我从 4 个元素的数组中选择一个值 4 次,则选择的值应该是随机的,但每次都不同。

如果我从同一个 4 个元素的数组中选择它 10 次,那么显然有些值会重复。

我现在有这个,但我仍然得到重复的值,即使循环运行了 4 次:

$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...
}

【问题讨论】:

  • 为什么不使用array_rand($arr_history, 4) 来随机获取数组呢?这可确保您有 4 个唯一值。在下一次迭代中,您会以不同的顺序获得数组。
  • 语句unset($arr_history[$selected]); 似乎将$arr_history 视为关联数组,因为$selected 是值,而不是索引。不过,这并不能解决问题。取消设置 $selected 应该将其从数组中删除,这意味着当循环完成时,数组是空的。那是你的意图吗? (我不这么认为)

标签: php arrays random


【解决方案1】:
$isShowCategory = array();
for ($i=0; $i <5 ; $i++) { 
   $myCategory = array_rand($arrTrCategoryApp,1); 
   if (!in_array($myCategory, $isShowCategory)) {
      $isShowCategory[] = $myCategory;

      #do something 

   }
}

【讨论】:

  • 在您的答案周围添加一些上下文(例如为什么它可以解决问题)将有助于其他人查看答案。
【解决方案2】:

简单干净:

$colors = array('blue', 'green', 'orange');
$history = $colors;

function getColor($colors, &$history){
    if(count($history)==0)
        $history = $colors;
    return array_pop( $history );
}

echo getColor($colors, $history);

【讨论】:

    【解决方案3】:

    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);
    
    ?>
    

    【讨论】:

      【解决方案4】:

      如果您不关心数组中的特定值,您可以尝试实现一个线性同余生成器来生成数组中的所有值。

      LCG implementation

      维基百科列出了一些您可以使用的值,以及为 LCG 算法选择值的规则,因为 LCG 算法是确定性的,它保证在周期长度之前不会重复单个值。

      用这个唯一的数字填充数组后,您可以简单地按顺序将数组中的数字 1 1 。

      【讨论】:

        【解决方案5】:

        如何改组数组并弹出项目。

        pop 返回null 时,重置数组。

        $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;
        }
        

        当然,你会想要更好地封装它,做更好的检查,以及其他类似的事情。

        【讨论】:

          【解决方案6】:

          Php 有一个名为shuffle 的本机函数,您可以使用它对数组中的元素进行随机排序。那么这个呢?

          $arr = ('abc', 'def', 'xyz', 'qqq');
          
          $random = shuffle($arr);
          
          foreach($random as $number) {
              echo $number;
          }
          

          【讨论】:

          • shuffle 实际上返回一个布尔值并修改原始数组,因此您需要foreach ($arr as $a)
          【解决方案7】:

          你几乎说对了。问题出在unset($arr_history[$selected]); 行。 $selected 的值不是键,实际上是一个值,因此 unset 不起作用。

          为了让它和你在那里的一样:

          <?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;
          }
          

          或者是少几行的例子:

          <?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;
          }
          

          【讨论】:

          • 谢谢这似乎有效,但奇怪的是这样的数组有键。我认为 key 和 value 都是一样的
          • @Alex - 不,事实上,当您不指定键时,PHP 会为它们分配从 0 开始的数字键。有关详细信息,请参阅http://ca3.php.net/manual/en/function.array.php 的参数部分。
          • 总是一样的结果,不是随机的
          【解决方案8】:

          我这样做是为了为用户创建一个随机的 8 位密码:

          $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];
          }
          

          【讨论】:

          • 你没有得到重复的字符吗?
          • 或者只是:substr(str_shuffle('abcdefghijklmnopqrstuvwxyz0123456789'), 0, 8) 这会更便宜。
          • @Alex - 是的。 @Leif - 你是对的更好,感谢您的洞察力!
          【解决方案9】:

          key != value,使用这个:

          $index = array_rand($arr_history, 1);
          $selected = $arr_history[$index];  
          unset($arr_history[$index]); 
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-06-30
            • 1970-01-01
            • 2012-07-11
            • 1970-01-01
            相关资源
            最近更新 更多