我正在尝试从数组中相对选择X值。例如,我想从以下数组中选择4个值:
arr = [1,2,3,4,5,6,7,8,9]
我现在正在做的是:
var newArr = [];
var pick = 4;
var delta = arr.length/pick;
for (i = 0; i < arr.length; i = i + delta) {
k = Math.floor(i);
newArr.push(arr[k]);
};
// then I'm cheating a bit
newarr[newArr.length-1] = arr[newArr.length-1];
我的问题是,在某些值(我在更长的数组上使用它)上,新数组比定义的pick变量更长。这与增量和随后的舍入有关,后者有时会附加一个值。
有人知道如何正确执行此操作吗?预期结果应为以下之一:
newArr = [1,3,6,9] || newArr = [1,4,6,9] || newArr = [1,4,7,9]
主要问题在以下行中:
var delta = arr.length/pick;
使用此delta值,您将使我在arr.length
循环的最后一次迭代中得出该值,这不是有效的索引。它应该(根据您的请求)到达数组的最后一个元素。另外,您也想从第一个值开始,因此您的增量应该更大(间隔由pick-1的部分确定),因此上面的语句应该是:
if (pick == 1) return [arr[0]]; // exceptional case
var delta = (arr.length-1)/(pick-1);
要处理浮点错误,最好使用,而round
不是floor
,这样,如果在最后一次迭代中i的值比其小一小部分arr.length-1
,仍将以该索引为目标。
为绝对确保生成所需数量的值,应使该数量计入循环条件。
最后,您似乎还想从数组中的第一个值开始,因此这意味着您不应该在选择第一个值之后才将增量添加到i值中。
综合所有这些,您可以达到以下功能:
function pickFrom(arr, pick) {
if (pick == 1) return [arr[0]]; // exceptional case
var newArr = [];
var delta = (arr.length-1)/(pick-1);
var k, i = 0;
while (pick--) {
k = Math.round(i);
newArr.push(arr[k]);
i = i + delta;
}
return newArr;
}
var arr = [1,2,3,4,5,6,7,8,9]
var res = pickFrom(arr, 4);
console.log(res);
.as-console-wrapper { max-height: 100% !important; top: 0; }
注意:请始终使用var
(或const
,let
)定义变量。
这是实现相同功能的简洁ES6函数:
function pickFrom(arr, pick) {
var delta = (arr.length-1)/Math.max(1, pick-1);
return Array.from(Array(pick), (_, i) => arr[Math.round(i*delta)])
}
var arr = [1,2,3,4,5,6,7,8,9]
var res = pickFrom(arr, 4);
console.log(res);
.as-console-wrapper { max-height: 100% !important; top: 0; }
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句