【问题标题】:JavaScript array reduce start from indexJavaScript 数组减少从索引开始
【发布时间】:2016-05-04 04:57:18
【问题描述】:

这个问题已经困扰我一段时间了,我似乎无法在网络上找到答案。

是否可以从某个索引开始使用Array reduce方法?

简单例子

var studentGrades = ["John Doe", "Some School", 6, 7, 8, 7, 9, 9];

如果我只需要循环 studentGrades 中的整数,我可以用一个简单的 for 循环来做到这一点

for(var i = 2; i < studentGrades.length; i++) {
  // do stuff here ...
}

但是假设我需要得到一个平均成绩,即所有整数的总和除以整数计数。如果 Array 只包含整数,那么使用 reduce 就没有问题。

var onlyIntegersArr = [5,2,3,4];
var averageGrade = onlyIntegersArr.reduce(function(a,b){
  return a + b;
}) / onlyIntegersArr.length;

但是,如果我知道出于某种原因我需要跳过前两个 Array 元素并从索引 Array[2] 开始。

例如,我会将 reduce 应用于 studentGrades,但仅从索引 studentGrades[2] 开始。

reduce 有可能吗?

感谢您的解决方案,我喜欢 slice 方法,但在这种情况下我不喜欢使用新方法。

例如

var average = studentGrades.reduce(function(a,b,i){
  return i >= 2 ? a+b : 0;
}) / (studentGrades.length - 2);

【问题讨论】:

  • array.slice(2).reduce(...
  • if 条件怎么样?

标签: javascript arrays reduce


【解决方案1】:

reduce的第三个参数是一个索引,这里是fiddle

var averageGrade = onlyIntegersArr.reduce(function (a, b, c) {
    if (c >= 2) {
        return a + b;
    } else {
        return 0;
    }
});

如果数组在第二个索引之后有更多非数字项,请检查此fiddle

var studentGrades = ["John Doe", "Some School", 6, 7, 8, 7, 9, 9, "Some School"];
var averageGrade = studentGrades.reduce(function (a, b, c) {
    if (c >= 2 && !isNaN(b)) {
        return a + b;
    } else if (c >= 2) {
        return a + 0;
    } else {
        return 0;
    }
})
alert(averageGrade);

【讨论】:

  • 这会失败:var studentGrades = ["John Doe", "Some School", 6, 7,'test'];
  • @RayonDabre 是真的,但这不是 OP 所要求的。无论如何,如果 OP 要求,让我也检查一下 isNaN。
  • 我会接受这个解决方案,因为它最适合我的问题。我不需要使用新的数组方法,而只需在 reduce 方法中使用 index 参数。我不知何故忽略了它。
  • 我喜欢较短的解决方案,例如onlyIntegersArr.reduce((a, b, c) =&gt; (c &gt;= 2 ? a + b : 0))
  • 我同意,但我喜欢这个解决方案,因为它是唯一指出使用 reduce index 参数的解决方案。
【解决方案2】:

如果您知道要跳过第一个 n 元素,则可以使用 Array#slice

使用 ES2015 Arrow Function

var sum = array.slice(n).reduce((a, b) => a + b);

var studentGrades = ["John Doe", "Some School", 6, 7, 8, 7, 9, 9];
var sum = studentGrades.slice(2).reduce((a, b) => a + b);

document.body.innerHTML = 'SUM is = ' + sum;

在 ES5 中,可以使用匿名函数编写相同的代码。

var sum = array.slice(n).reduce(function(a, b) {
    return a + b;
});

var studentGrades = ["John Doe", "Some School", 6, 7, 8, 7, 9, 9];
var sum = studentGrades.slice(2).reduce(function(a, b) {
    return a + b;
});

document.body.innerHTML = 'SUM is = ' + sum;

对于您提到的情况,仅将数值相加,而不管它们在数组中的哪个位置 - 您可以执行类似的操作

var sum = array.reduce(function(result, v) {
    return result + (parseFloat(v) || 0);
}, 0);

var studentGrades = ["John Doe", "Some School", 6, 7, 8, 7, 9, 9];
var sum = studentGrades.reduce(function(result, v) {
    return result + (parseFloat(v) || 0);
}, 0);

document.body.innerHTML = 'SUM is = ' + sum;

【讨论】:

  • @fast,是的,确实如此,如果你有数十亿个元素,那肯定是个问题
  • 感谢@Tushar 为编辑答案所付出的辛勤工作,使其看起来和读起来都很好
【解决方案3】:

如果你确定你总是只需要索引 2 以后,那么这就足够了

var onlyIntegersArr = studentGrades.slice(2);
var averageGrade = onlyIntegersArr.reduce(function(a,b){
    return a + b;
}) / onlyIntegersArr.length;

然而,如果你想得到所有的整数,那么你需要过滤数组

var onlyIntegersArr = studentGrades.filter(function(val) {
    return (val === parseInt(val, 10));
});
var averageGrade = onlyIntegersArr.reduce(function(a,b){
    return a + b;
}) / onlyIntegersArr.length;

【讨论】:

    【解决方案4】:

    你为什么要把事情复杂化?为什么不:

    function avg(arr)
    {
         var sum = 0;
         var l = 0;
         for(var i = 0; i < arr.length; i++)
         {
            if(isNaN(1*arr[i])) continue;
            sum += arr[i];
            l++;
         }
         return sum/l;
    }
    

    也许您需要考虑将数据保存在对象中,其中所有成绩都在单独的数组中。其他数据在属性中。您可以从您拥有的数组中对其进行序列化,然后使用该对象。

    【讨论】:

      猜你喜欢
      • 2022-12-17
      • 2016-01-19
      • 1970-01-01
      • 1970-01-01
      • 2015-05-02
      • 2019-11-26
      • 2016-12-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多