我有一个while循环,应该在2维中随机植入numberOfTruth真值。我只是要更改它们,如果它们还不为真,并且只能更改numberOfTruths次:
function truthfulArray(maxY, maxX, numberOfTruths, array) {
var x;
var y;
var counter = 0;
while (counter < numberOfTruths) {
x = generateRandomNumber(maxX);
y = generateRandomNumber(maxY);
if (!array[x][y]) {
array[x][y] = true;
counter++;
}
}
return array;
}
我可以看到与二维数组大小有关的优化问题,并且随着numberOfTruths接近maxY和maxX的乘积,它将浪费大量资源来完成任务。我想知道我可以对功能进行哪些调整以使其更有效。预先感谢!
*** generateRandomNumber(max)
是一个简单的函数,它返回从0到输入的最大值的随机数。
答案 0 :(得分:0)
基于@Bergi的评论,这是一种优化。它假定数组开头是空的(或者,它不在乎,只是覆盖了东西)。
当填充因子(N / (X * Y)
)低时(使用X = Y = 500进行测试),它会变慢,但似乎比原始实现要快40%,并且果断地快(例如3倍) 80%。 (您可能希望将其用作试探法。)
通常的想法是,我们首先从行的开头填充随机行,然后使用Fisher-Yates随机播放将每一行分散开。与原始版本相比,我已经将y
和x
进行了转换,因为这就是我习惯于处理2D数组的方式。 :D
function shuffle(array) { // h/t https://bost.ocks.org/mike/shuffle/
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;
}
function truthfulArrayFillRows(maxY, maxX, numberOfTruths, array) {
var nLeft = numberOfTruths;
var nSeededPerRow = new Array(maxY).fill(0);
// Seed rows randomly with trues starting from the left
while(nLeft > 0) {
var y = generateRandomNumber(maxY);
var x = nSeededPerRow[y];
if(x < maxX) {
array[y][x] = true;
nLeft --;
nSeededPerRow[y] ++;
}
}
// Shuffle the rows we seeded
for(var y = 0; y < maxY; y++) {
if(nSeededPerRow[y] > 0) {
shuffle(array[y]);
}
}
return array;
}
答案 1 :(得分:0)
您可以从所有可能的职位中随机选择numberOfTruth
个职位,而可以从许多有效职位中随机选择numberOfTruth
个职位。为此,您必须先找到那些位置。
function shuffle(a) {
var j, x, i;
for (i = a.length - 1; i > 0; i--) {
j = Math.floor(Math.random() * (i + 1));
x = a[i];
a[i] = a[j];
a[j] = x;
}
return a;
}
function chunkArray(myArray, chunk_size){
var results = [];
while (myArray.length) {
results.push(myArray.splice(0, chunk_size));
}
return results;
}
function flatten(array) {
var flattened=[];
for (var i=0; i<array.length; ++i) {
var current = array[i];
for (var j=0; j<current.length; ++j)
flattened.push(current[j]);
}
return flattened;
}
function truthfulArray(maxY, maxX, numberOfTruths, array){
var flatArray = flatten(array);
var validPositions = flatArray.map(function(e, i){if(!e) return i});
var randomPositions = shuffle(validPositions).slice(0, numberOfTruths);
randomPositions.forEach(function(i){flatArray[i] = true;});
return chunkArray(flatArray, maxY);
}
var maxX = 20, maxY = 30;
var array = Array(maxX).fill(Array(maxY).fill(false));
truthfulArray(maxY, maxX, 40, array);
这种方法是否更有效取决于您的数据。如果有很多有效的职位可供选择,那么您的代码应该完全有效。数组中的true
越多,您的代码(随机)命中它们的可能性就越小。在这种情况下,我描述的方法将更加有效。
希望对您有所帮助。