我有一个由25个插槽组成的数组,我需要将前5个数字设置为1-15,接下来的5个数字设置为16-30,依此类推。
我已经完成了一个for循环和一个switch案例来实现此目的,但是它返回了错误的值。在forloop之外,它返回正确的数字。
var num = [];
var col = [0,0,0,0,0,1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,4,4,4,4,4];
var card = [];
// Filling the num array
function fill(number) {
for(let i = 1; i < number+1; i++) {
num.push([i]);
} // Fills the array from 1 to 'number' and will have no duplicates
}
fill(76);
function fillCard() {
for(let i = 0; i < col.length; i++) {
switch (col[i]) {
case 0:
getRandom(0,15);
break;
case 1:
getRandom(16,30);
break;
case 2:
getRandom(31,45);
break;
case 3:
getRandom(46,60);
break;
case 4:
getRandom(61,75);
break;
default:
console.log('error');
}
}
}
function getRandom(min,max) {
var x = Math.floor(Math.random() * (max - min + 1) ) + min;
card.push(num[x]);
num.splice(x,1);
}
答案 0 :(得分:2)
后续评论清楚地表明,这是试图在每个部分中包含不重复的随机数。
这可能是我的方法:
function randoms(max, count) {
// todo: error if count > max
const arr = new Array(max + 1)
for (let i = max; i > max - count; i--) {
const j = Math.floor(Math.random() * (i + 1))
const temp = arr[j] || j
arr[j] = arr[i] || i
arr[i] = temp
}
return arr.slice(-count)
}
const ranges = [ [1, 15], [16, 30], [31, 45], [46, 60], [61, 75] ]
const makeCard = (ranges, count) => ranges.map(
([min, max]) => randoms(max - min + 1, count).map(n => n + min)
).reduce((a, b) => a.concat(b), [])
console.log(makeCard(ranges, 5))
randoms
是Fisher-Yates随机播放的一种版本,在对固定数量的值进行随机播放后会停止。 (我是从我的earlier answer那里拿来的。)。每个对此的调用都会在0 - (max - min)
范围内选择五个不同的数字,然后在内部min
调用中向其中添加map
。
map
中的外部makeCard
调用为每个范围调用随机函数,这将产生如下结果:
[
[15, 10, 14, 12, 5],
[17, 30, 29, 20, 16],
[35, 34, 31, 46, 37],
[53, 58, 46, 54, 60],
[70, 65, 75, 74, 62]
]
然后,我们在结果上调用reduce
并传递一个函数,该函数将其两个参数简单地连接起来,从而将其转换为一个列表。在某些时候,我们将可以改用Array.prototype.flat
。
此方法的一个优点是您可以轻松更改范围列表,因此它们不必都具有相等的长度。而且,如果您希望对范围使用不同的计数,则也可以在范围内移动count
变量(例如,[ [5, 16, 30], [7, 31, 50] ]
用于“在16和60之间选择5个不同的数字,在31和50之间选择7个不同的数字。”这将仅涉及对代码的小改动。
(旧答案)
对代码进行的最小更改即可完成您想要的操作,只是将您选择的值直接推到数组上即可。 (我不知道num
应该在这里。)此版本可以做到这一点:
var col = [0,0,0,0,0,1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,4,4,4,4,4];
var card = [];
function fillCard() {
for(let i = 0; i < col.length; i++) {
switch (col[i]) {
case 0:
getRandom(0,15);
break;
case 1:
getRandom(16,30);
break;
case 2:
getRandom(31,45);
break;
case 3:
getRandom(46,60);
break;
case 4:
getRandom(61,75);
break;
default:
console.log('error');
}
}
}
function getRandom(min,max) {
var x = Math.floor(Math.random() * (max - min + 1) ) + min;
card.push(x)
}
fillCard()
console.log(card)
但是,如果您对更高级的技术感兴趣,可以简单地写:
const card = [...new Array(25)].map(
(_, i) => Math.floor(Math.random() * 15) + (15 * Math.floor(i / 5)) + 1
)
console.log(card)
第二个版本以[...new Array(25)]
开始。 new Array(25)
部分将创建一个数组,该数组不包含任何实际元素,但人工长度为25。用花括号([ ]
)和散布运算符(...
)包裹起来,将其变成数组具有25个实际值,所有这些值恰好是undefined
。
[undefined, undefined, undefined, ... undefined]
现在,我们可以在该数组上map
,这是对每个值应用函数以创建全新数组的过程。我们传递给地图的功能是
(_, i) => Math.floor(Math.random() * 15) + (15 * Math.floor(i / 5)) + 1,
它有两个参数,但是由于我们将忽略第一个参数,因此我们将其命名为_
。这个名字没有魔力,但是向读者发出一个普遍信号,即该参数并不重要。不过,我们使用第二个参数。 i
是我们正在查看的数组中的索引。
其余的是相当简单的数学。 5
代表每个组中的元素数。 15
代表随机范围的大小。如果需要,我们可以编写一个接受这两个值作为参数并返回数组的函数。
答案 1 :(得分:0)
因此,有些事情出了问题-您正在根据更改的值进行循环,但是每次将i
设置为可能会超出循环长度的值。< / p>
仔细研究一下逻辑,然后告诉我这是否正确:
Task: create an array of 25 numbers, each lot of five to be in a different range. The first five between 0 and 15, the next five between 16 and 30, the next five between 31 and 45, the next 46 to 60, and final five between 61 and 75.
* Create an array to define the 'steps'. Based on those steps, we switch our min and max for these array values.
* Create an array to store each of the random numbers.
* While we have a valid length of 'steps' array, use the first to define the current range.
* Use a switch statement to determine the min/max of the current random member.
* remove the first member of the 'steps' array.
如果这些步骤与您正在考虑的步骤相似,则可能是您想得太多了。相反,只需执行以下操作即可:使用while
循环,检查col.length
仍大于零,然后基于col[0]
进行切换。
这是它的外观:
var col = [0,0,0,0,0,1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,4,4,4,4,4];
var card = [];
function fillCard() {
while(col.length > 0) {
switch (col[0]) {
case 0:
getRandom(0,15);
break;
case 1:
getRandom(16,30);
break;
case 2:
getRandom(31,45);
break;
case 3:
getRandom(46,60);
break;
case 4:
getRandom(61,75);
break;
default:
console.log('error');
}
}
}
function getRandom(min,max) {
var x = Math.floor(Math.random() * (max-min) ) +min;
card.push(x);
col.shift();
}
fillCard();
console.log(card)
编辑:上面的方法很好,对于我们给的原始规格。但是,如果您需要在该范围内生成UNIQUE随机数,则需要执行其他过程:
这是可能的编码方式:
let col = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4],
possibles = [],
card = [];
function fillCard() {
/**
* First, create an array of possible values. This will be a nested
* array, each sub-array containing fifteen unique sequential
* values within our given range.
*/
for (let i = 0; i <= 4; i++) {
let possibleSubArray = [];
for (let j = 0; j <= 15; j++) {
possibleSubArray.push(i * 15 + j);
}
possibles.push(possibleSubArray);
}
// Let's see that list of possibles.
// console.log(possibles);
// Now, we use col to identify which of the sub-arrays we want to
// get our unique value from.
for (let i = 0; i < col.length; i++) {
// getRandom no longer takes a min/max. Now it takes the index
// to the given sub-array.
getRandom(col[i]);
}
// This creates a random number based on the length of the subarray
// length, then pushes the value at that index onto our 'card'
// array. At that point, it removes that number from our 'possibles'
// array, thus rendering it unique.
function getRandom(possiblesSubArrayIndex) {
let min = 0, max = possibles[possiblesSubArrayIndex].length;
var x = Math.floor(Math.random() * (max - min)) + min;
// push that random number onto our 'card'
card.push(possibles[possiblesSubArrayIndex][x]);
// and remove it from the possible numbers.
possibles[possiblesSubArrayIndex].splice(x, 1);
}
}
fillCard();
console.log(card);
// If you want to see what we DIDN'T use for uniques...
// console.log(possibles);
答案 2 :(得分:0)
我认为,这对您有用。
Math.floor(Math.random()* max + 1 , min)