相对地从数组中选择X值

Relatively pick X values out of Array

本文关键字:选择 数组 相对      更新时间:2023-09-26

我试图从数组中相对地选择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这个值,您将使i在循环的最后一次迭代时到达值arr.length,这不是一个有效的索引。它应该到达(根据您的请求)数组的最后一个元素。此外,您还希望从第一个值开始,因此您的增量应该更大(间隔由pick-1 parts决定),因此上面的语句应该是:

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; }

我建议只使用从0到pick的计数器循环,并对每个元素进行乘法运算,并获得计算的整数值的索引。

var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9],
    newArr = [],
    pick = 4,
    delta = arr.length / pick,
    i = 0;
while (i < pick) {
    newArr.push(arr[Math.floor(i * delta)]);
    i++;
}
console.log(newArr);