我有一个包含10个数字的数组:
var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
我编写了一个函数(下面),从数组中返回一个随机元素,而不重复返回相同的元素,直到返回了8个其他元素。它工作但似乎非常低效,因为在代码可以继续之前,通常需要多次调用随机数生成器。有没有更有效的方法来实现相同的结果?
var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var recentlyReturned = [];
function minimalRepeat() {
var i = Math.floor(Math.random() * 10);
while( recentlyReturned.indexOf(i) != -1 ) {
i = Math.floor(Math.random() * 10);
}
recentlyReturned.push(i);
while(recentlyReturned.length>8) {
recentlyReturned.shift();
}
return array[i];
}
for(var i=1; i<20; i++) {
console.log(minimalRepeat());
}
*编辑*
我根据Tudor Ilisoi的反馈改写了代码。它肯定更有效率。但是,可以跨越随机边界重复。
第2版:
function shuffle(arr) {
var copyArr = arr.slice();
for (let i = copyArr.length; i; i--) {
let j = Math.floor(Math.random() * i);
[copyArr[i - 1], copyArr[j]] = [copyArr[j], copyArr[i - 1]];
}
return copyArr;
}
var a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var b = shuffle(a);
for(var i=1; i<20; i++) {
if(b.length == 0) {
b = shuffle(a);
}
console.log(b.pop());
}
答案 0 :(得分:0)
你可以这样做:
copy
copy.pop()
的随机副本中提取,直到副本为空(或者提取了8个元素)。满足此条件时,请另外制作副本通过从随机副本中提取,您确保在再次生成副本之前不会返回相同的元素。
根据评论反馈进行修改
function shuffle(arr) {
var copyArr = arr.slice();
for (let i = copyArr.length; i; i--) {
let j = Math.floor(Math.random() * i);
[copyArr[i - 1], copyArr[j]] = [copyArr[j], copyArr[i - 1]];
}
return copyArr;
}
var latest = []
var a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var b = shuffle(a);
for (var i = 1; i < 20; i++) {
if (b.length == 0) {
b = shuffle(a);
}
var popped = b.pop()
//if found in recents
if (latest.indexOf(popped) !== -1) {
continue;
}
//push the popped element
latest.push(popped)
if (latest.length > 8) {
latest.shift() //remove the oldest "recent" to keep the "latest" length at 8
}
console.log(popped);
}
&#13;
答案 1 :(得分:0)
费 - 耶茨:
function shuffle(array) {
var m = array.length, t, i;
while (m) {
i = Math.floor(Math.random() * m--);
t = array[m];
array[m] = array[i];
array[i] = t;
}
return array;
}
var origArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var numbers = origArray;
var randomNumbers = shuffle(numbers);
var result = randomNumbers.slice(0, 8);
for (var i = 0; i < 11; i++) {
result.push(randomNumbers[Math.floor(Math.random() * (origArray.length-1))]);
}
前8个数字应该是唯一的(来自预设集) 接下来的11个数字可以是所选数字和预定义集合中的重复数字。
(如果我正确理解了这个问题。)
根据评论进行修改
由于 no-repeat-window 为8,因此您将从阵列中留下两个数字;最后两个数字。
下一个随机数是数组中的第一个数字。
您可以将pop
和shift
这些数字放入一个临时数组中,将临时数组和push
临时数组混淆回随机数组。
var origArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var randomNumbers = shuffle(origArray);
for (var i = 0; i < 19; i++)
{
var tmp = [];
tmp.push(randomNumbers.pop()); // First number not in no-repeat-window
tmp.push(randomNumbers.pop()); // Second number not in no-repeat-window
tmp.push(randomNumbers.shift()); // Current random number.
randomNumbers.push.apply(randomNumbers, shuffle(tmp));
}
答案 2 :(得分:0)
您可以在数组中组织循环队列:
Randomize array A[] with Fisher-Yates algo
Set Idx to 0
At every step generate random r = 0 or 1
If r=1 swap A[Idx % 10] and A[(Idx + 1) % 10]
Output A[Idx % 10]
Increment Idx