如何在JavaScript中检查数组是否递增?

5

我正在学习JavaScript课程,现在遇到了一些问题。我们得到一个充满练习的网站,并且必须使所有测试用例都变成绿色。

我们需要检查一个数组是否递增,如果是,则返回true。如果下一个值与上一个值相同,则函数也必须返回true。但是我的所有测试用例都出现了错误?如果我删除else语句,则只有一个测试用例是错误的(这个:[0,1,2,3,4,5,0])。这里是测试用例。

function isIncreasing(xs) {
    var result = false;
    if (xs.length == 1 || xs.length === 0) {
        return true;
    }
    for (var i = 0; i <= xs.length - 1; i++) {
        if (xs[i] == xs[i + 1] - 1 || xs[i] == xs[i + 1]) {
            result = true;
        }
        else return false;
    }
    return result;
}
5个回答

3

您的循环在最后一次迭代(i == xs.length - 1xs[i+1])时尝试访问超出数组边界的元素。更清洁的方法是从第二个元素开始,与前一个进行比较,而不是下一个。

function isIncreasing(xs) {
  
    for (var i = 1; i < xs.length; i++) {
        if (xs[i] !== xs[i - 1] && xs[i] != xs[i - 1] + 1) {
            return false;
        }
    }
  
    return true;
}

console.log(isIncreasing([]));
console.log(isIncreasing([1]));
console.log(isIncreasing([1,2,3,4,4,5]));
console.log(isIncreasing([0,1,2,3,4,5,0]))

此外,请注意您的函数如何简化(实际上不需要长度检查和结果变量)。

不,实际上原始代码包括了最后一个元素和一个超出最后一个元素的额外元素;它被给定为 i <= xs.length - 1,但应该是 i < xs.length - 1。另外规范似乎不太清楚——例如[1, 2, 3, 5]没有经过测试,但根据原始表达式,它可能会被禁止使用。 - Ken Y-N
当然!愚蠢的小错误,现在代码可以工作了,谢谢! - RandomStacker

3

使用调试器逐行查看代码并检查变量值,你应该能够很快找到问题所在。

如果你想使用 for 循环,可以简化代码,并省略对 0 和 1 的特殊情况处理,同时修复循环条件的顶部:

function isIncreasing(xs) {
  var prev, cur;

  for (var i = 0; i < xs.length; i++) {
    cur = xs[i];
    if (i && cur !== prev && cur !== prev + 1) return false;
    prev = cur;
  }

  return true;
}

如果您可以使用ES5数组方法,则可以使用every来实现此操作:
[1, 2, 3].every(function(elt, idx, arr) { 
  var prev = arr[idx - 1];
  return !idx || elt === prev || elt === prev + 1;
})

如果您想让您的代码更语义化和易读,请定义一个命名明确的函数:

function sameOrGreater(elt, idx, arr) { 
  var prev = arr[idx - 1];
  return !idx || elt === prev || elt === prev + 1;
}

[1, 2, 3].every(sameOrGreater)

继续这个因式分解,我们可以将解决方案分为两个方面。第一个是看一个值是否与另一个值相同或大于另一个值。第二个是取数组中相邻元素的一对。换句话说,我们希望能够将解决方案写成

pairs(xs).every(sameOrGreater)

sameOrGreater 很简单:

function sameOrGreater(x, y) { return x === y || x === y - 1; }

pairs可以按照以下方式编写:

function pairs(array) {
  return array.slice(1).map(function(elt, idx, arr) {
    return [array[idx], elt];
  });
}

> pairs([1, 2, 3])
< [[1, 2], [2, 3]]

您可能更喜欢使用生成器编写pairs

function* pairs(array) {
  let prev;
  for (const x of array) {
    yield [prev, x];
    prev = x;
  }
}

或者,我们可以编写一个版本的map函数,该函数接受一个将被输入一对值的函数,如下所示:

function mapPairs(xs, fn) {
  var result = [];
  for (var i = 1; i < xs.length); i++) {
    result.push(fn(x[i - 1], x[i]));
  }
  return result;
}

现在我们可以把整个问题写成:
mapPairs(xs, sameOrGreater).every(Boolean)

2

由于没有使用Array.prototype.reduce的答案,我认为它非常适合这个问题,因此这里提供了一个使用reduce的解决方案:

var arrayIsAscending = [-1, 13, 14].reduce((outcome, value, index, array) => {
  if (!outcome) return false // if at least one item failed, this will always return false
  if (index === 0) return true // first item cannot be checked against a previous item
  return value > array[index-1]
}, true)

console.log(arrayIsAscending)

当然,传递给reduce的函数可以被提取出来并赋予一个名称。

0

也许我们可以像这样进行调整:

var isIncreasing = (arr) => {
  return (
    arr.every((v, i) => i === 0 || v >= arr[i - 1])
  );
};

console.log(isIncreasing([]));
console.log(isIncreasing([0]));
console.log(isIncreasing([1, 0]));
console.log(isIncreasing([1, 1, 1]));
console.log(isIncreasing([1, 1, 2, 3, 3]));
console.log(isIncreasing([0, 1, 2, 3, 4, 5, 0]))


0
  isIncreasing = (array) => {
    for(i = 0; i <= array.length; i++){
      if(array[i] < array[i + 1]) {}
      else if (i <= array.length && array[i] < array[i + 1]) return true;
      else return false;
    }
  }

这段代码使用for循环迭代数组的索引,并检查比它大的索引是否更大。因为return停止函数执行,我添加了一个if语句来检查它是否正在递增。如果是递增,则不做任何操作,但如果不是,则停止函数执行,因为它没有递增。else if只是检查是否在不出错的情况下到达了最后一个索引。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接