如何确保不会重复输入随机数?现在,这不起作用。我正在使用本地数组存储以前的结果。
getUniqueRandomNumber(x){
var index;
var viewedIndices = [];
index = Math.floor(Math.random() * (x));
if(viewedIndices.includes(index))
{
viewedIndices.push(index);
this.getUniqueRandomNumber(x);
}
else {
console.log(index);
return index;
}
}
答案 0 :(得分:3)
您需要使viewedIndicies
持久,以便进一步调用getUniqueRandomNumber
可以看到先前添加的元素。与其跟踪标记,不如跟踪所选的简单数字 可能会更容易。您可以使用Set而不是数组来降低计算复杂度(.has
是O(1)
,.includes
是O(N)
)。
const makeGetUniqueRandomNumber = (x) => {
const chosenNumbers = new Set();
return () => {
if (chosenNumbers.size === x) {
throw new Error('No more uniques!');
}
let num;
do {
num = Math.floor(Math.random() * x);
} while (chosenNumbers.has(num));
chosenNumbers.add(num);
return num;
};
};
const getRand5 = makeGetUniqueRandomNumber(5);
console.log(
getRand5(),
getRand5(),
getRand5(),
getRand5(),
getRand5()
);
try {
getRand5();
} catch(e) {
console.log(e.message);
}
const anotherGetRand5 = makeGetUniqueRandomNumber(5);
console.log(
anotherGetRand5(),
anotherGetRand5(),
anotherGetRand5(),
anotherGetRand5(),
anotherGetRand5()
);
您还可以提前生成整个随机数数组,然后每次选择另一个splice
,但是当可能性很大但只需要几个随机数时,效率会很低数字。正确的选择取决于一个会话中所需唯一编号与随机范围大小的比例。
如果在不了解ES6(ES2015)语法的古老环境中进行开发,则可以使用数组而不是Set,并通过Babel传递代码:
"use strict";
var makeGetUniqueRandomNumber = function makeGetUniqueRandomNumber(x) {
var chosenNumbers = [];
return function () {
if (chosenNumbers.length === x) {
throw new Error('No more uniques!');
}
var num;
do {
num = Math.floor(Math.random() * x);
} while (chosenNumbers.includes(num));
chosenNumbers.push(num);
return num;
};
};
var getRand5 = makeGetUniqueRandomNumber(5);
console.log(getRand5(), getRand5(), getRand5(), getRand5(), getRand5());
try {
getRand5();
} catch (e) {
console.log(e.message);
}
var anotherGetRand5 = makeGetUniqueRandomNumber(5);
console.log(anotherGetRand5(), anotherGetRand5(), anotherGetRand5(), anotherGetRand5(), anotherGetRand5());
答案 1 :(得分:2)
您有两个错误,oné是每次尝试都会清除的函数内部的数组,然后有错误的逻辑以无限循环结尾。
const usedIndexes = [];
function getUniqueRandomNumber(x) {
const index = Math.floor(Math.random() * (x));
if (usedIndexes.includes(index)) {
return this.getUniqueRandomNumber(x);
} else {
console.log(index);
usedIndexes.push(index);
return index;
}
}
此外,我会考虑在这种情况下使用Set
而不是数组。
const usedIndexes = new Set();
function getUniqueRandomNumber(max, min = 0) {
const newNumber = Math.floor(Math.random() * (max - min) + min);
if (usedIndexes.has(newNumber)) {
return this.getUniqueRandomNumber(max, min);
} else {
usedIndexes.add(newNumber);
return newNumber;
}
}
我还编辑了变量名以更好地反映它们的实际用法,并为随机数添加了最小值。
答案 2 :(得分:0)
这不起作用,因为每次调用 getUniqueRandomNumber 时,它将 viewedIndices 数组重新初始化为空数组。因此,为了使您的代码正常工作,请在函数调用上方声明此数组。
答案 3 :(得分:0)
您是只希望编写的代码正常工作还是想要更好的解决方案?选择随机数直到不重复为止,这是灾难的根源,因为程序会停顿几秒钟,试图找到一个尚未使用的数字。当然,如果您只要求提供几个数字,也许并不需要花很多时间,但是代码位于您的代码库中,并且从现在起5年后,其他人正在使用它,而他们不知道代码中存在定时炸弹。想象一下,数组中有10000个元素,并且已选择9999个元素。可能需要一百万次重试才能最终选择一个未使用的索引。
该代码似乎正在选择变量名称为index
和viewedIndices
的索引
一种选择随机元素的方法是只是从数组中随机删除然后删除。如果需要复制数组
const array = ["a", "b", "c", "d", "e", "f", "g"];
while (array.length) {
const ndx = Math.random() * array.length | 0;
const elem = array.splice(ndx, 1)[0];
console.log(elem);
}
注意:使用Math.random() * value | 0
获得随机数0->正整数比Math.floor(Math.random() * value)
快,因为|
是运算符,而不是附加到Math
对象的函数必须在每次通话时检查该电话,以查看是否已被替换。