【问题标题】:Generating unique sets of numbers from given range从给定范围生成唯一的数字集
【发布时间】:2019-02-08 13:27:02
【问题描述】:

目前我正在使用以下脚本从给定范围生成随机数集,在本例中为 1-20。但是此代码生成的数字集可能不止一次具有相同的数字。我需要的是从给定范围内生成唯一的随机集。集合中不能重复任何数字,所有数字都应该使用一次。

所以在这种情况下,如果我想要 1-20 范围内的 5 个数字组,则将有 4 个组,每个数字将使用一次。或者如果我想要 4 个数字的集合,那么将有 5 个具有唯一随机数的集合。

基本上,我想从给定范围内获取所有具有唯一随机数的集合。

我怎样才能得到这个结果?

管理员注意:我查看了以前的帖子,虽然在各种语言中都有类似的问题,但在 php.ini 中没有类似的帖子。谢谢。

<form method="POST" action="">
      <label for="Numbers">Numbers</label>
      <input type="checkbox" id="sets" name="sets" value="numbersets"><br />
   <p><input type="submit" value="submit"/></p>
</form>

<?php
function Numbers($min_number, $max_number, $amount_of_numbers)
{
    $range = range($min_number, $max_number);
    shuffle($range);
    $numbers_array = array_slice($range, 0, $amount_of_numbers);
    natsort($numbers_array);
    return array_values($numbers_array);
}

if (isset($_POST['sets'])) {
        echo "<h2>Sets</h2>";
  $number_set = array();
        for ($i = 1; $i <= 4; $i++) { 
            $number_set = Numbers(1, 20, 5);  
            echo implode(",", $number_set) . "<br />";
        }
}


?>

【问题讨论】:

  • 不太清楚。您希望将 X 个随机数分成 Y 个部分且没有重复?
  • 是的,完全正确。谢谢。不过应该随机完成。
  • 它总是可以被 Y 部分整除。不会有像 4 / 21 这样的情况。

标签: php


【解决方案1】:

使用array_chunk 代替array_slice 并在函数中准备完整的多维数组。

然后将其传回并回显每个子数组。

function Numbers($min_number, $max_number, $amount_of_numbers)
{
    $range = range($min_number, $max_number);
    shuffle($range);
    $numbers_array = array_chunk($range, $amount_of_numbers);
    foreach($numbers_array as &$arr){
        natsort($arr);
    }
    return array_values($numbers_array);
}


echo "<h2>Sets</h2>\n";
$number_set = Numbers(1, 20, 5);  
foreach($number_set as $set){
    echo implode(",", $set) . "<br />\n";
}

输出(例如,因为它是随机的):

<h2>Sets</h2>
7,10,12,15,16<br />
4,6,8,14,17<br />
1,2,11,13,19<br />
3,5,9,18,20<br />

https://3v4l.org/foqIH

【讨论】:

  • 注意如果$amount_of_numbers$min_number$max_number之间的差值有余数,那么最后一个数组会被分片,不包含$amount_of_numbers声明的元素个数(对不起英语)。
  • 例如$min_number = 1; $max_number = 5; $amount_of_numbers = 3,你会得到[[1, 2, 3], [4, 5]]
【解决方案2】:

生成一次随机数组,然后将其切片。

$range = range(1, 20);
shuffle($range);

$number_set = array();
$offset = 0;

for ($i = 1; $i <= 4; $i++) {
    $numbers_array = array_slice($range, $offset, 5);
    natsort($numbers_array);
    $number_set = array_values($numbers_array);
    $offset += 5;
}

【讨论】:

    【解决方案3】:

    先生成整个列表再拆分比较容易。

    <?php
    function Numbers($min_number, $max_number, $number_of_groups)
    {
        // +1 needed because (for example) min: 4, max: 5 -> 5 - 4 = 1, but there are 2 possible values, not just 1
        $size_of_set = (int)floor(($max_number - $min_number + 1) / $number_of_groups);
    
        if ($size_of_set == 0) {
            // Handle corner cases
            // ...
        }
    
        $range = range($min_number, $max_number);
        shuffle($range);
    
        $results = array();
        for ($i = 0; $i < $number_of_groups; $i++) {
            $results[$i] = array_slice($range, $i*$size_of_set, $size_of_set);
            natsort($results[$i]);
        }
        return $results;
    }
    
    if (isset($_POST['sets'])) {
            echo "<h2>Sets</h2>";
            $number_set = Numbers(1, 20, 4);
            for ($i = 0; $i < sizeof($number_set); $i++) {
                echo implode(",", $number_set[$i]) . "<br />";
            }
    }
    ?>
    

    编辑

    刚刚意识到,您不需要在$size_of_set = (int)floor(...) 使用(int)floor(...),因为所有数字都是整数 -> 计算返回整数。

    【讨论】:

      猜你喜欢
      • 2012-12-02
      • 1970-01-01
      • 1970-01-01
      • 2012-03-18
      • 2012-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多