消除数组中的项目以达到固定长度 - JavaScript
Eliminate Items From Array To Reach Fixed Length - JavaScript
我正在尝试编写一个 JavaScript 函数来从数组中删除项目以达到定义的长度。该函数应该通过数组均匀地消除“间隙”。我需要这个函数来简化 canvas 绘图的多边形顶点。
它应该是这样工作的:
这是我想出的代码:
function simplify(array, vertices) {
// Calculate gap size
var gap = array.length - vertices;
gap = Math.floor(array.length / gap);
var count = 0;
var result = [];
// Fill a new array
for (var i = 0; i < array.length; i++) {
if (count == gap) {
count = 0;
} else {
result.push(array[i]);
count++;
}
}
// Eliminate 1 item in the middle if length is odd
if (result.length > vertices) {
result.splice(Math.floor(result.length / 2), 1);
}
return result;
}
// This gives the wrong result depending on the length of the input!
// The result should be an array with the length of 3
console.log(simplify([
{ x: 10, y: 20 },
{ x: 30, y: 40 },
{ x: 40, y: 50 },
{ x: 50, y: 60 }
], 3))
然而,这似乎只是有时有效,问题可能出在数学上。什么算法可以实现这个或者我做错了什么?
如果您只想消除项目以将该数组剪切到所需的长度。使用 Array.splice() 函数。
例如,如果您的 desiredLength = 3
。你有一个 array = [1,2,3,4,5]
.
array.splice(0,desiredLength).length == desiredLength
应该是真的。
也许这会 help
假设您有一个长度为 n 的字符串,并且您希望它的长度为 m。您有 n-2 个元素可供选择,m-2 个元素可供选择用于您的新数组。现在,假设您当前选择了 i 个元素并传递了 j 个元素。如果 i/j < (m-2)/(n-2) 那么你落后了。你可能应该采取另一个元素。对于最大均匀选择,您真正想知道的是 (i+1)/(j+1) 或 i/(j+1) 是否更接近您的目标 (m-2)/(n-2 ).如果溢出不是问题,你可以做一点代数来弄清楚这是否等同于 (i+1)(n-2) - (j+1)( m-2) 大于或小于 (n-2)/2; more 意味着 i 更好(所以不要拿这个),而 less 意味着 i+1 更好。
我用最近邻纹理查找的相同方法解决了这个问题。浮点步长变量(大于零)下一个较低的索引,但是当 'floor(i*step)' 大于 'i' 时,它需要第一次跳转。
function simplify(array, vertices){
vertices = vertices || 1;///No div by zeros please :)
var result = [];
var step = array.length/vertices;
for(var i=0;i<vertices;i++){
result.push(array[Math.floor(step*i)]);
}
return result;
}
//Testing it out
var testarr = [];
for(var ai=0;ai<51;ai++){
testarr[ai] = {
x:ai,
y:10*ai
}
}
console.log(testarr.slice(0));
var ret = simplify(testarr, 29);
console.log(ret.slice(0));
顺便说一句,
function simplify_bilinear(array, vertices){
var result = [];
var step = array.length/vertices;
for(var i=0;i<vertices;i++){
var fistep = Math.floor(i*step);//The nearest neighbor index
var current = array[fistep];//This element
var next = array[fistep+1];//The next element
var mix = (i*step)-fistep;//The fractional ratio between them. As this approaches 1, the mix approaches the next value.
//mix = mix * mix * (3 - 2 * mix);//Optional (s-curve) easing between the positions. Better than linear, anyway.
//Alternately to the above//mix = Math.sin((mix*2 - 1)*Math.PI)*.5+.5;///for a sinusoid curve
//True Bezier would be optimal here but beyond this scope
var mixed_point = {
x:current.x+(next.x-current.x)*mix,//basic mixing, ala 'mix' in your average math library
y:current.y+(next.y-current.y)*mix,
}
result.push(mixed_point);
}
return result;
}
是一个双线性 mag-filter,如果你想增加计数而不是降低计数。如果所需长度 ('vertices') 大于 'array.length',这可能会分支。也是软件音频合成的有用算法。
我正在尝试编写一个 JavaScript 函数来从数组中删除项目以达到定义的长度。该函数应该通过数组均匀地消除“间隙”。我需要这个函数来简化 canvas 绘图的多边形顶点。
它应该是这样工作的:
这是我想出的代码:
function simplify(array, vertices) {
// Calculate gap size
var gap = array.length - vertices;
gap = Math.floor(array.length / gap);
var count = 0;
var result = [];
// Fill a new array
for (var i = 0; i < array.length; i++) {
if (count == gap) {
count = 0;
} else {
result.push(array[i]);
count++;
}
}
// Eliminate 1 item in the middle if length is odd
if (result.length > vertices) {
result.splice(Math.floor(result.length / 2), 1);
}
return result;
}
// This gives the wrong result depending on the length of the input!
// The result should be an array with the length of 3
console.log(simplify([
{ x: 10, y: 20 },
{ x: 30, y: 40 },
{ x: 40, y: 50 },
{ x: 50, y: 60 }
], 3))
然而,这似乎只是有时有效,问题可能出在数学上。什么算法可以实现这个或者我做错了什么?
如果您只想消除项目以将该数组剪切到所需的长度。使用 Array.splice() 函数。
例如,如果您的 desiredLength = 3
。你有一个 array = [1,2,3,4,5]
.
array.splice(0,desiredLength).length == desiredLength
应该是真的。
也许这会 help
假设您有一个长度为 n 的字符串,并且您希望它的长度为 m。您有 n-2 个元素可供选择,m-2 个元素可供选择用于您的新数组。现在,假设您当前选择了 i 个元素并传递了 j 个元素。如果 i/j < (m-2)/(n-2) 那么你落后了。你可能应该采取另一个元素。对于最大均匀选择,您真正想知道的是 (i+1)/(j+1) 或 i/(j+1) 是否更接近您的目标 (m-2)/(n-2 ).如果溢出不是问题,你可以做一点代数来弄清楚这是否等同于 (i+1)(n-2) - (j+1)( m-2) 大于或小于 (n-2)/2; more 意味着 i 更好(所以不要拿这个),而 less 意味着 i+1 更好。
我用最近邻纹理查找的相同方法解决了这个问题。浮点步长变量(大于零)下一个较低的索引,但是当 'floor(i*step)' 大于 'i' 时,它需要第一次跳转。
function simplify(array, vertices){
vertices = vertices || 1;///No div by zeros please :)
var result = [];
var step = array.length/vertices;
for(var i=0;i<vertices;i++){
result.push(array[Math.floor(step*i)]);
}
return result;
}
//Testing it out
var testarr = [];
for(var ai=0;ai<51;ai++){
testarr[ai] = {
x:ai,
y:10*ai
}
}
console.log(testarr.slice(0));
var ret = simplify(testarr, 29);
console.log(ret.slice(0));
顺便说一句,
function simplify_bilinear(array, vertices){
var result = [];
var step = array.length/vertices;
for(var i=0;i<vertices;i++){
var fistep = Math.floor(i*step);//The nearest neighbor index
var current = array[fistep];//This element
var next = array[fistep+1];//The next element
var mix = (i*step)-fistep;//The fractional ratio between them. As this approaches 1, the mix approaches the next value.
//mix = mix * mix * (3 - 2 * mix);//Optional (s-curve) easing between the positions. Better than linear, anyway.
//Alternately to the above//mix = Math.sin((mix*2 - 1)*Math.PI)*.5+.5;///for a sinusoid curve
//True Bezier would be optimal here but beyond this scope
var mixed_point = {
x:current.x+(next.x-current.x)*mix,//basic mixing, ala 'mix' in your average math library
y:current.y+(next.y-current.y)*mix,
}
result.push(mixed_point);
}
return result;
}
是一个双线性 mag-filter,如果你想增加计数而不是降低计数。如果所需长度 ('vertices') 大于 'array.length',这可能会分支。也是软件音频合成的有用算法。