我有以下功能
function randomNum(max, used){
newNum = Math.floor(Math.random() * max + 1);
if($.inArray(newNum, used) === -1){
console.log(newNum + " is not in array");
return newNum;
}else{
return randomNum(max,used);
}
}
基本上我创建一个1到10之间的随机数,并检查是否已经创建了该数字,方法是将其添加到数组并检查新创建的数字。我通过将其添加到变量来调用它。
UPDATED:
for(var i=0;i < 10;i++){
randNum = randomNum(10, usedNums);
usedNums.push(randNum);
//do something with ranNum
}
这样可行,但在Chrome中我收到以下错误:
Uncaught RangeError: Maximum call stack size exceeded
我猜这是因为我在内部调用函数的次数太多了。这意味着我的代码不好。
有人可以帮我逻辑吗?什么是确保我的数字不重复的最佳方法?
答案 0 :(得分:24)
如果我理解的话,你只是在寻找数字1-10的排列(即随机数没有重复)? 也许尝试生成这些数字的随机列表,一次,在开始时,然后只是通过那些?
这将计算nums
中数字的随机排列:
var nums = [1,2,3,4,5,6,7,8,9,10],
ranNums = [],
i = nums.length,
j = 0;
while (i--) {
j = Math.floor(Math.random() * (i+1));
ranNums.push(nums[j]);
nums.splice(j,1);
}
因此,举例来说,如果您正在寻找1到20之间的偶数,那么您也可以使用:
nums = [2,4,6,8,10,12,14,16,18,20];
然后只需阅读ranNums
以便回忆随机数。
正如您在方法中所发现的那样,不会花费更长的时间来查找未使用的数字。
编辑:在阅读this并在jsperf上运行测试后,看起来更好的方法是使用Fisher-Yates Shuffle:
function shuffle(array) {
var i = array.length,
j = 0,
temp;
while (i--) {
j = Math.floor(Math.random() * (i+1));
// swap randomly chosen element with current element
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
var ranNums = shuffle([1,2,3,4,5,6,7,8,9,10]);
基本上,通过避免使用“昂贵的”阵列操作来提高效率。
BONUS EDIT :另一种可能是使用generators(假设您有support):
function* shuffle(array) {
var i = array.length;
while (i--) {
yield array.splice(Math.floor(Math.random() * (i+1)), 1)[0];
}
}
然后使用:
var ranNums = shuffle([1,2,3,4,5,6,7,8,9,10]);
ranNums.next().value; // first random number from array
ranNums.next().value; // second random number from array
ranNums.next().value; // etc.
一旦您浏览了混洗数组中的所有元素,ranNums.next().value
最终将评估为undefined
。
总的来说,这不会像Fisher-Yates Shuffle那样有效,因为你仍然是splice
一个数组。但不同之处在于,您现在只在需要时才开展这项工作,而不是提前完成,因此根据您的使用情况,这可能会更好。
答案 1 :(得分:2)
试试这个:
var numbers = []; // new empty array
var min, max, r, n, p;
min = 1;
max = 50;
r = 5; // how many numbers you want to extract
for (let i = 0; i < r; i++) {
do {
n = Math.floor(Math.random() * (max - min + 1)) + min;
p = numbers.includes(n);
if(!p){
numbers.push(n);
}
}
while(p);
}
console.log(numbers.join(" - "));
答案 2 :(得分:2)
//random number without repetition in JavaScript, Just in one line;
//it can be used as _id;
//it not need to store or check;
const myRnId = () => parseInt(Date.now() * Math.random());
console.log(myRnId()); // any random number included timeStamp;
答案 3 :(得分:1)
const GenerateRandomNumbers = (max) => {
let orderNumbers = new Set();
for (let i = 1; ;i++){
let random = Math.floor(Math.random() * max + 1) ;
orderNumbers.add(random);
if (orderNumbers.size == max){
break;
}
}
return orderNumbers;}
答案 4 :(得分:1)
//companion object
object MyModel {
implicit def myModelOptOptDecoder[A](implicit d: Decoder[A]): Decoder[Option[Option[A]]] =
MyHelperObject.optOptDecoder
implicit val myModelDecoder: Decoder[MyModel] = deriveDecoder
}
由于保护子句( <form asp-action="myActionMethod" method="post">
<h3>Do you like pizza?</h3>
<div class="checkbox">
<label>
<input asp-for="likesPizza"/> Yes
</label>
</div>
</form>
),一旦满足参数,该函数将停止执行。
答案 5 :(得分:1)
let arr = [];
do {
let num = Math.floor(Math.random() * 10 + 1);
arr.push(num);
arr = arr.filter((item, index) => {
return arr.indexOf(item) === index
});
} while (arr.length < 10);
console.log(arr);
答案 6 :(得分:1)
问题在于,当您接近饱和度时,您会开始花费更长时间来“随机”生成唯一数字。例如,在上面提供的示例中,max是10.一旦使用的数字数组包含8个数字,可能需要很长时间才能找到第9个和第10个数字。这可能是生成最大调用堆栈错误的地方。
的 jsFiddle Demo showing iteration count being maxed
强> 的
通过在递归内部迭代,您可以看到当数组完全饱和时会发生大量执行,但会调用该函数。在这种情况下,函数应退出。
的 jsFiddle Demo with early break
强> 的
if( used.length >= max ) return undefined;
完成迭代检查和无限递归的最后一种方法就是 jsFiddle Demo
:
function randomNum(max, used, calls){
if( calls == void 0 ) calls = 0;
if( calls++ > 10000 ) return undefined;
if( used.length >= max ) return undefined;
var newNum = Math.floor(Math.random() * max + 1);
if($.inArray(newNum, used) === -1){
return newNum;
}else{
return randomNum(max,used,calls);
}
}
答案 7 :(得分:0)
randojs.com使它成为简单的单行代码:
randoSequence(1, 10)
这将以随机顺序返回从1到10的数字数组。 您只需要在html文档的开头添加以下内容,就可以轻松随机地完成几乎所有您想做的事情。数组中的随机值,随机jquery元素,对象中的随机属性,甚至可以防止重复,如我在此处所示。
<script src="https://randojs.com/1.0.0.js"></script>
答案 8 :(得分:0)
HTML
<p id="array_number" style="font-size: 25px; text-align: center;"></p>
JS
var min = 1;
var max = 90;
var stop = 6; //Number of numbers to extract
var numbers = [];
for (let i = 0; i < stop; i++) {
var n = Math.floor(Math.random() * max) + min;
var check = numbers.includes(n);
if(check === false) {
numbers.push(n);
} else {
while(check === true){
n = Math.floor(Math.random() * max) + min;
check = numbers.includes(n);
if(check === false){
numbers.push(n);
}
}
}
}
sort();
//Sort the array in ascending order
function sort() {
numbers.sort(function(a, b){return a-b});
document.getElementById("array_number").innerHTML = numbers.join(" - ");
}
答案 9 :(得分:0)
Future<Configure> conf = getLatestVersion(request);
conf.onComplete( res -> {
if( res.succeded() ){
Configure cc = res.result();
float previousVersion = cc.getVersionNo();
}
} );
答案 10 :(得分:0)
while(randArr.length < SIZEOFARRAY){
val = Math.floor((Math.random() * RANGEOFVALUES));
if(randArr.indexOf(val) < 0){
randArr.push(val);
}
}
您可以将 SIZEOFARRAY 更改为要使用的数组的大小 并将 RANGEOFVALUES 更改为您希望随机化的值范围
答案 11 :(得分:0)
如果不需要排列和/或长度是可变的,这是非重复的随机列表/数组的一种解决方案,没有 if语句:
myArrayOrList[key]
// no repeat if old_key is provided
function myShuffle(arr_or_list, old_key = false) {
var keys = Array.from(Object.keys(arr_or_list)); //extracts keys
if (old_key != false) {
keys.splice(keys.indexOf(old_key), 1); // removes old_key from keys
};
var randomKey = keys[Math.floor(Math.random() * keys.length)]; // get random key
return randomKey;
}
//test:
const a = [10, 20, 30, 40, 50, 60];
const b = {
"a": 10,
"bla-bla bla": 20,
"d": 30,
"c": 40
};
var oldKeys_a = [];
var oldKeys_b = [];
oldKeys_a[0] = myShuffle(a);
oldKeys_b[0] = myShuffle(b);
var i;
for (i = 1; i < 10; i++) {
oldKeys_a[i] = myShuffle(a, oldKeys_a[i - 1]);
oldKeys_b[i] = myShuffle(b, oldKeys_b[i - 1]);
}
alert('oldKeys_a: ' + oldKeys_a + '; oldKeys_b: ' + oldKeys_b)
//random...
//>>> oldKeys_a: 1,3,0,0,5,0,4,5,2,3; oldKeys_b: d,a,d,bla-bla bla,a,c,d,bla-bla bla,a,d <<<
答案 12 :(得分:0)
仅供参考的解决方案
const fiveNums = () => {
const ranNum = () => Math.floor(Math.random() * (10 + 1));
let current;
let arr = [];
while(arr.length < 5) {
if(arr.indexOf(current = ranNum()) === -1) {
arr.push(current);
}
}
return arr;
};
fiveNums();
答案 13 :(得分:0)
对不起,这是一个旧问题的新答案,但这可以通过地图更有效地完成。你所追求的是随机选择而不是非重复随机。非重复随机是荒谬的。
其中_a是集合,而r不是集合的一部分,我们lambda随机值r:
function aRandom(f){
var r = Math.random();
aRandom._a[r] ? aRandom(f) : f(r,aRandom._a[r] = 1);
}
aRandom._a = {};
//usage:
aRandom(function(r){ console.log(r) });
当浏览器变得缓慢时重新定义aRandom._a。为了避免最终的迟缓,人们应该真正使用具有足够熵的UUID生成算法,以便重复的机会实际上为零,而不是暴力强制可分性。我选择了函数名称aRandom,因为拉丁语前缀A-表示“远离”。由于使用的越多,输出越远离随机。该功能在Macbook上在2100毫秒内产生一百万个唯一值。
上述解决方案的优点是不需要限制该组。同样,多个呼叫者可以同时使用它,并假设它们的值与所有其他呼叫者不同。这对于诸如保险没有重叠的噪声抖动分布这样的事情是很方便的。
但是,它也可以修改为返回整数,以便将ram使用限制为所提供的长度:
function aRandom(f,c){
var r = Math.floor(Math.random()*c);
aRandom._a[r] ? aRandom(f,c) : f(r,aRandom._a[r] = 1);
}
aRandom._a = {};
//usage:
var len = 10;
var resultset = [];
for(var i =0; i< len; i++){
aRandom(function(r){ resultset.push(r); }, len);
}
console.log(resultset);
答案 14 :(得分:0)
AND ((@ExcludeCB=1 and tn.tt !='CB') or @ExcludeCB=0)
答案 15 :(得分:0)
这是我使用underscore.js
实现的方法从n
到min
值获取max
个整数。其中n
是size
参数。
var randomNonRepeatingIntFromInterval = function(min, max, size) {
var values = [];
while (values.length < size) {
values.push(Math.floor(Math.random() * ( max - min + 1) + min));
values = _.uniq(values);
}
return values;
}
答案 16 :(得分:0)
function randomNumbers(max) {
function range(upTo) {
var result = [];
for(var i = 0; i < upTo; i++) result.push(i);
return result;
}
function shuffle(o){
for(var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
return o;
}
var myArr = shuffle(range(max));
return function() {
return myArr.shift();
};
}
构建一个小测试,在jsfiddle上尝试:
var randoms = randomNumbers(10),
rand = randoms(),
result = [];
while(rand != null) {
result.push(rand);
rand = randoms();
}
console.log(result);
随机播放功能由dzone.com提供。
答案 17 :(得分:-2)
你真的不想丢失随机数字。真正的随机数必须能够重复。
真正的随机数就像掷骰子一样。接下来会出现任何数字。
随机播放的数字就像绘制扑克牌一样。每个号码只能出现一次。
你真正要求的是随机播放一个数字列表,然后使用洗牌列表中的第一个这么多数字。
考虑按顺序制作数字列表,然后使用随机数生成器从该列表的副本中随机选择一个数字。每次都将所选数字放在新列表的末尾,并将其从旧列表的副本中删除,从而缩短该列表。完成后,新列表将包含随机数字,旧列表的副本将为空。
或者,您可以选择所选的数字并立即使用它,通过删除使用的数字来缩短列表的副本。由于您已从列表中删除了该号码,因此无法再次显示该号码。