我正在尝试将1D数组分解为2D数组,其中子数组的长度不同。这种变化应遵循高斯曲线(或丘形)。因此,假设我们制作的2D数组变量名为gaussianCurve。 gaussianCurve [0]和gaussianCurve [n]中的数组长度为1,而gaussianCurve [n / 2]则为参数“ maxArrayLength”提供的最大值。这迫使gaussianCurve索引的数量变为可变的。
说我有以下伪代码:
function (oneDimentionalArray, maxArrayLength) {
// oneDimentionalArray is ["A","B","C","D","E","F","G","H","I","J","K"]
// maxArrayLength is 5
// Currently working like this (i.e. "batches"):
// return [["A","B","C","D","E"],["F","G","H","I","J"],["K"]]
// would LIKE it to work like this
gaussianCurve = []
gaussianCurve.push(["A"])
gaussianCurve.push(["B", "C"])
gaussianCurve.push(["D", "E", "F", "G", "H"])
gaussianCurve.push(["I", "J"])
gaussianCurve.push(["K"])
return gaussianCurve
}
我为什么要这样的东西?进度条。
欢迎提出任何建议。我只是在脑海中看不到答案。
编辑:我觉得它的措词很差,所以我要改写它。
... gaussianCurve [0] .length和gaussianCurve [gaussianCurve.length-1] .length将为1,而gaussianCurve [gaussianCurve.length / 2] .length将达到“ maxArrayLength”。
输入:
function gaussianRefactor(["A","B","C","D","E","F","G","H","I","J","K"], 1)
function gaussianRefactor(["A","B","C","D","E","F","G","H","I","J","K"], 2)
function gaussianRefactor(["A","B","C","D","E","F","G","H","I","J","K"], 4)
function gaussianRefactor(["A","B","C","D","E","F","G","H","I","J","K"], 8)
function gaussianRefactor(["A","B","C","D","E","F","G","H","I","J","K"], 16)
输出:
[["A"],["B"],["C"],["D"],["E"],["F"],["G"],["H"],["I"],["J"],["K"]]
[["A"],["B","C"],["D","E"],["F","G"],["H","I"],["J"],["K"]]
[["A"],["B","C","D"],["E","F","G","H"],["I","J","K"]]
[["A"],["B","C","D","E","F","G","H","I"],["J","K"]]
[["A","B","C","D","E","F","G","H","I","J","K"]]
任何内部数组都不能超过maxArrayLength的长度
答案 0 :(得分:2)
我给了它一个快速的镜头,它似乎起作用了。一些潜在的改进:
function probability(s, m, x) {
var eExp = -Math.pow(x - m, 2) /
(2 * Math.pow(s, 2));
return 1/(Math.sqrt(2*Math.PI) * s) *
Math.pow(Math.E, eExp);
}
function gassianArray(input, nBins) {
// first try to determine a reasonable value of s so that the outer bins have a value
var s = 0.1;
var sMax = 10;
var m = (nBins - 1) / 2.0;
var outerBinMinimum = 1 / input.length;
var p = 0;
while (true && s <= sMax) {
p = probability(s, m, 0);
if (p >= outerBinMinimum) {
break;
} else {
s += 0.1;
}
}
// holds arrays
var output = [];
// holds desired array sizes
var outputLengths = [];
// fill these based on probability density
for (var b=0; b<nBins; b++) {
var n = Math.floor(probability(s, m, b) * input.length);
output.push([]);
outputLengths.push(n);
}
// fill arrays from outside, leaving extra values for the middle
var midIndex = Math.floor(m);
// left side
for (var i=0; i<midIndex; i++) {
for (var j=0; j<outputLengths[i]; j++) {
output[i].push(input.shift());
}
}
// right side
for (var i=nBins-1; i>=midIndex; i--) {
for (var j=0; j<outputLengths[i]; j++) {
output[i].push(input.pop());
}
output[i].reverse();
}
// whatever remains goes in the "middle"
while (input.length !== 0) {
output[midIndex].unshift(input.pop());
}
return output;
}
var input = ["A","B","C","D","E","F","G","H","I","J","K"];
var n = 5;
console.log(gassianArray(input, n));
/*
[ [ 'A' ],
[ 'B', 'C' ],
[ 'E', 'D', 'F', 'G', 'H' ],
[ 'I', 'J' ],
[ 'K' ] ]
*/
var input = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];
var n = 6;
console.log(gassianArray(input, n));
/*
[ [ 'A' ],
[ 'B', 'C', 'D', 'E' ],
[ 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N' ],
[ 'O', 'P', 'Q', 'R', 'S', 'T', 'U' ],
[ 'V', 'W', 'X', 'Y' ],
[ 'Z' ] ]
*/
答案 1 :(得分:1)
非常有趣的挑战。 :)
我玩了一点,这是我想出的:
function chunk(arr, start, n) {
if (arr.length < n) {
return null;
}
return arr.splice(start, n);
}
function gaussianArray(arr, max) {
const len = arr.length;
if (max > len) {
return [arr];
}
const curve = [];
// Extract middle.
const mid = Math.floor(len / 2);
const startIndex = mid - (max / 2) + 1;
const highest = arr.splice(startIndex, max);
curve.push(highest);
// Splits the rest in 2 arrays; left side and right side, middle already excluded.
const leftArr = arr.slice(0, startIndex);
const rightArr = arr.slice(startIndex, len);
let leftMax = max;
let rightMax = max;
// Adds chunks from left side.
while (leftArr.length) {
const leftChunk = chunk(leftArr, leftArr.length - leftMax, leftMax);
if (leftChunk) {
curve.unshift(leftChunk);
} else {
leftMax--;
}
}
// Adds chunks from right side.
while (rightArr.length) {
const rightChunk = chunk(rightArr, 0, rightMax);
if (rightChunk) {
curve.push(rightChunk);
} else {
rightMax--;
}
}
return curve;
}
console.log(JSON.stringify(gaussianArray(["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K"], 1)));
console.log(JSON.stringify(gaussianArray(["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K"], 2)));
console.log(JSON.stringify(gaussianArray(["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K"], 4)));
console.log(JSON.stringify(gaussianArray(["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K"], 8)));
console.log(JSON.stringify(gaussianArray(["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K"], 16)));
这不是您想要的,但是我认为它应该很接近解决进度条问题...
答案 2 :(得分:0)
这更符合我的想法。我非常不喜欢找到sigma的方式。我知道我应该对公式重新排序以进行计算,但是我尚未使它起作用。无论如何,这是“答案”,尽管它对于我在问题中作为示例提供的较小数组失败,但它成功完成了我需要做的事情。如果有人想改进,请告诉我。
var gaussianRefactor = function(srcOneDimentionalArray, srcMaxArrayLength) {
var finalArray = [];
if (srcOneDimentionalArray.length <= srcMaxArrayLength) {
finalArray.push(srcOneDimentionalArray);
return finalArray;
}
if (srcMaxArrayLength === 1) {
for(var lengthOne = 0; lengthOne < srcOneDimentionalArray.length; lengthOne++)
finalArray.push([srcOneDimentionalArray[lengthOne]]);
return finalArray;
}
var maxArrayLength = srcMaxArrayLength;
var oneDimentionalArray = srcOneDimentionalArray.slice(0);
for (var x = srcMaxArrayLength; x > 1 && maxArrayLength / oneDimentionalArray.length > 0.3333; x--) {
maxArrayLength--;
}
var standardChunkSize = srcOneDimentionalArray.length / maxArrayLength;
var predictedSize = (3 * Math.floor(standardChunkSize)) % 2 === 0 ? 3 * Math.floor(standardChunkSize) + 1 : 3 * Math.floor(standardChunkSize);
var predictedSizeCenter = Math.ceil(predictedSize / 2);
var sigma = 0.2034185 * Math.pow(standardChunkSize, 1.963449);
var multiplicand = 1 / (Math.sqrt(sigma) * Math.sqrt(2 * Math.PI));
var centerGauss = maxArrayLength / multiplicand;
var mu = 0;
var delta;
var fraction;
var exponent;
var full;
var subArrayLength;
var subArray;
var notWideEnough = true;
var maxElements;
var maxAttempts = Math.max(Math.ceil(sigma), 100);
var currentAttempts = 0;
while (notWideEnough && currentAttempts < maxAttempts) {
maxElements = 0;
for (var j = 0; j < predictedSize; j++) {
delta = (j - predictedSizeCenter) - mu;
fraction = delta / Math.sqrt(sigma);
exponent = -0.5 * Math.pow(fraction, 2);
full = multiplicand * Math.exp(exponent);
subArrayLength = Math.floor(full * centerGauss);
maxElements += subArrayLength;
}
if (maxElements >= srcOneDimentionalArray.length) {
notWideEnough = false;
} else {
sigma = sigma + sigma * 0.05;
}
currentAttempts++;
}
if (currentAttempts === maxAttempts) {
return false;
}
for (var i = 0; i < predictedSize; i++) {
delta = (i - predictedSizeCenter) - mu;
fraction = delta / Math.sqrt(sigma);
exponent = -0.5 * Math.pow(fraction, 2);
full = multiplicand * Math.exp(exponent);
subArrayLength = Math.floor(full * centerGauss);
if (subArrayLength < 1 || oneDimentionalArray.length < 1) {
continue;
}
subArray = oneDimentionalArray.slice(0, subArrayLength);
oneDimentionalArray = oneDimentionalArray.slice(subArrayLength, oneDimentionalArray.length);
finalArray.push(subArray);
}
return finalArray;
}
输入
gaussianRefactor(["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K"], 1)
gaussianRefactor(["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K"], 2)
gaussianRefactor(["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K"], 4)
gaussianRefactor(["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K"], 8)
gaussianRefactor(["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K"], 16)
输出
[["A"],["B"],["C"],["D"],["E"],["F"],["G"],["H"],["I"],["J"],["K"]]
[["A"],["B"],["C"],["D"],["E"],["F","G"],["H"],["I"],["J"],["K"]]
[["A"],["B"],["C","D"],["E","F","G"],["H","I"],["J"],["K"]]
[["A"],["B"],["C","D"],["E","F","G"],["H","I"],["J"],["K"]]
[["A","B","C","D","E","F","G","H","I","J","K"]]