生成0到‘x’之间唯一随机数(整数)

58

我需要生成一组独一无二且在0和给定数字之间的整数。

也就是说:

var limit = 10;
var amount = 3;

我该如何使用 JavaScript 生成三个介于 1 和 10 之间的唯一数字?


1
дҪ жҳҜжҢҮиҢғеӣҙеңЁ1вүӨxвүӨ10зҡ„3дёӘж•ҙж•°пјҢиҝҳжҳҜиҢғеӣҙеңЁ1вүӨx<10зҡ„дёүдёӘжө®зӮ№ж•°пјҹ - Jeremy
4
“重复问题”不是正确的问题。这个问题包含一个“额外”的要求:随机数应该是“唯一”的。 - Rob W
这个回答解决了你的问题吗?在JavaScript中生成特定范围内的随机整数? - Michael Freidgeim
16个回答

0
/**
 * Generates an array with numbers between
 * min and max randomly positioned.
 */
function genArr(min, max, numOfSwaps){
  var size = (max-min) + 1;
  numOfSwaps = numOfSwaps || size;
  var arr = Array.apply(null, Array(size));

  for(var i = 0, j = min; i < size & j <= max; i++, j++) {
    arr[i] = j;
  }

  for(var i = 0; i < numOfSwaps; i++) {
    var idx1 = Math.round(Math.random() * (size - 1));
    var idx2 = Math.round(Math.random() * (size - 1));

    var temp = arr[idx1];
    arr[idx1] = arr[idx2];
    arr[idx2] = temp;
  }

  return arr;
}

/* generating the array and using it to get 3 uniques numbers */
var arr = genArr(1, 10);
for(var i = 0; i < 3; i++) {
  console.log(arr.pop());
}

0

我几年前写了这段C#代码,它是从维基百科记录的算法中派生而来的,现在我已经忘记了(欢迎评论...)。HashSet的生命周期内保证唯一性。显然,如果您将使用数据库,可以在那里存储生成的数字。对于我的需求,随机性还可以,但可能可以通过使用不同的RNG进行改进。注意:计数必须小于等于最大值-最小值(duh!),您可以轻松修改以生成无符号长整型。

private static readonly Random RndGen = new Random();

public static IEnumerable<int> UniqueRandomIntegers(int count, int min, int max)
{
    var rv = new HashSet<int>();
    for (var i = max - min - count + 1; i <= max - min; i++)
    {
       var r = (int)(RndGen.NextDouble() * i);
       var v = rv.Contains(r) ? i : r;
       rv.Add(v);
       yield return v;
    }
}

0

这是基于ES6 Set(“仅包含唯一值的数组”)的另一个可能解决方案。

使用示例:

// Get 4 unique rnd. numbers: from 0 until 4 (inclusive):
getUniqueNumbersInRange(4, 0, 5) //-> [5, 0, 4, 1];

// Get 2 unique rnd. numbers: from -1 until 2 (inclusive):
getUniqueNumbersInRange(2, -1, 2) //-> [1, -1];

// Get 0 unique rnd. numbers (empty result): from -1 until 2 (inclusive):
getUniqueNumbersInRange(0, -1, 2) //-> [];

// Get 7 unique rnd. numbers: from 1 until 7 (inclusive):
getUniqueNumbersInRange(7, 1, 7) //-> [ 3, 1, 6, 2, 7, 5, 4];

实现:

function getUniqueNumbersInRange(uniqueNumbersCount, fromInclusive, untilInclusive) {

    // 0/3. Check inputs.
    if (0 > uniqueNumbersCount) throw new Error('The number of unique numbers cannot be negative.');
    if (fromInclusive > untilInclusive) throw new Error('"From" bound "' + fromInclusive
        + '" cannot be greater than "until" bound "' + untilInclusive + '".');
    const rangeLength = untilInclusive - fromInclusive + 1;
    if (uniqueNumbersCount > rangeLength) throw new Error('The length of the range is ' + rangeLength + '=['
        + fromInclusive + '…' + untilInclusive + '] that is smaller than '
        + uniqueNumbersCount + ' (specified count of result numbers).');
    if (uniqueNumbersCount === 0) return [];


    // 1/3. Create a new "Set" – object that stores unique values of any type, whether primitive values or object references.
    // MDN - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set
    // Support: Google Chrome 38+(2014.10), Firefox 13+, IE 11+
    const uniqueDigits = new Set();


    // 2/3. Fill with random numbers.        
    while (uniqueNumbersCount > uniqueDigits.size) {
        // Generate and add an random integer in specified range.
        const nextRngNmb = Math.floor(Math.random() * rangeLength) + fromInclusive;
        uniqueDigits.add(nextRngNmb);
    }


    // 3/3. Convert "Set" with unique numbers into an array with "Array.from()".
    // MDN – https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from
    // Support: Google Chrome 45+ (2015.09+), Firefox 32+, not IE
    const resArray = Array.from(uniqueDigits);
    return resArray;

}

当前实现的优势:

  1. 具有基本的输入参数检查 - 当范围太小等情况时,您将不会得到意外输出。
  2. 支持负范围(不仅仅是从0开始),例如:-1000至500的随机数等。
  3. 预期行为:当前最流行的答案将自动扩展范围(上限),如果输入边界太小则会自己进行扩展。例如:获取指定范围从0到10的10000个唯一数字需要由于范围太小而引发错误(只有11个可能的唯一数字)。但当前的最佳答案将隐含地扩展范围直到10000。

0

我认为,这是最人性化的方法(使用while循环中的break),我在注释中解释了它的机制。

function generateRandomUniqueNumbersArray (limit) {

    //we need to store these numbers somewhere
    const array = new Array();
    //how many times we added a valid number (for if statement later)
    let counter = 0;

    //we will be generating random numbers until we are satisfied
    while (true) {

        //create that number
        const newRandomNumber = Math.floor(Math.random() * limit);

        //if we do not have this number in our array, we will add it
        if (!array.includes(newRandomNumber)) {
            array.push(newRandomNumber);
            counter++;
        }

        //if we have enought of numbers, we do not need to generate them anymore
        if (counter >= limit) {
            break;
        }
    }

    //now hand over this stuff
    return array;
}

当然,您可以在最后一个“if”语句中添加不同的限制(您的数量),如果您需要更少的数字,但请确保它小于或等于数字本身的限制-否则它将成为无限循环。


-1
const getRandomNo = (min, max) => {
   min = Math.ceil(min);
   max = Math.floor(max);
   return Math.floor(Math.random() * (max - min + 1)) + min; 
}

这个函数返回在指定范围内的随机整数。返回的值不小于min(如果min不是整数,则返回比min大的下一个整数),且小于(但不等于)max。 示例

console.log(`Random no between 0 and 10 ${getRandomNo(0,10)}`)

这不会返回像OP所要求的独特数字。 - ashleedawg

-2

这里有一个简单的一行解决方案:

var limit = 10;
var amount = 3;

randoSequence(1, limit).slice(0, amount);

它使用randojs.com生成从1到10的随机整数数组,并在第三个整数之后截断所有内容。如果您想使用此答案,请将其放置在HTML文档的head标签中:

<script src="https://randojs.com/1.0.0.js"></script>

嗯,如果需要一个2KB+、118行(美化后)的外部JS文件才能工作,我认为这不能算作一个 "一行解决方案"... 否则,按照这样的逻辑,任何可能的任务都可以有 "一行解决方案", 只要我们把所有的JS都倒进一个单独的文件中。(另外,你的答案是4行加上文件,不是1行。) - ashleedawg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接