使用 reduce() 方法在连续数字数组中查找跳过的数字

Use reduce() method to find a skipped number in an array of consecutive numbers

我正在尝试使用 reduce() 方法在一组(有时几乎是)连续数字中查找一个跳过(缺失)的数字。最多只会少一个数。 这是我的代码笔:http://codepen.io/PiotrBerebecki/pen/zBrRVd

例如,
findMissing([1,2,3,5]) 应该 return 4

findMissing([1,2,3,4]) 应该 return undefined

findMissing([2,3,4,6]) 应该 return 5

findMissing([2,4,5,6]) 应该 return 3

如果确实有一个数字被跳过,我开发的代码似乎可以正常工作。但如果所有数字都存在,它 return 是一个不需要的值。你知道怎么解决吗?

我的JS代码:

function findMissing(arr) {
  return arr.reduce(function(prev, curr) { 
    if (curr - prev !== 1) {
      return curr - 1;
    }
  });
}


// This should return 4, and it indeed returns 4
console.log(   findMissing([1,2,3,5])   );


// This should return 'undefined', but it returns 3
console.log(   findMissing([1,2,3,4])   );


// This should return 5, and it indeed returns 5
console.log(   findMissing([2,3,4,6])   );

更新 1:

根据以下答案,以下代码使用 reduce() 方法提供了预期的结果:

// ****SOLUTION:****
function findMissing2(arr) {
  return arr.reduce(function(prev, curr, index, array) {
    if (curr === index + array[0]) {
      return prev;
    } else {
      return index + array[0]++;
    }
  }, void 0);
}

console.log(   findMissing2([1,2,3,4])   ); // Undefined
console.log(   findMissing2([1,2,3,5])   ); // 4
console.log(   findMissing3([2,3,4,6])   ); // 5
console.log(   findMissing2([2,3,4,5])   ); // Undefined
console.log(   findMissing2([2,4,5,6])   ); // 3

您的 reduce closure/callback 函数需要 return 下一次迭代中用作下一个 prev 的值。

因此,在第二个例子中,第一次迭代returns undefined,因为它没有进入if块。第二次迭代传递了 undefined, 3 的参数,其中 undefined - 3 !== 1 所以它 returns 2.

这会传播你的迭代,直到它 returns 3.

因此,我正在努力想办法调整您的 reduce 函数来纠正此问题。

也许使用一个简单的 for 循环会更健壮一些?

function findMissing(arr) {
   for(var i = 1; i < arr.length; i++) {
       if(arr[i] - arr[i-1] !== 1) {
           return arr[i]-1;
       }
   }
}

您应该在此处使用 for 循环而不是 reduce

function findMissing(arr) {
  var r = [];
  for (var i = arr[0]; i <= arr[arr.length - 1]; i++) {
    if (arr.indexOf(i) == -1) r.push(i);
  }
  return r;
}


console.log(findMissing([1, 2, 3, 5]));
console.log(findMissing([1, 3, 6]));
console.log(findMissing([10, 13, 16]));

我会按照以下方式完成这项工作;

var a1 = [1,2,3,5],
    a2 = [2,3,4,5],
    a3 = [2,4,5,6],
  res1 = a1.reduce((p,c,i,a) => c == i+a[0] ? p : i + a[0]++, void 0),
  res2 = a2.reduce((p,c,i,a) => c == i+a[0] ? p : i + a[0]++, void 0),
  res3 = a3.reduce((p,c,i,a) => c == i+a[0] ? p : i + a[0]++, void 0);
console.log(res1);
console.log(res2);
console.log(res3);

注意:void 0在JS中是一个非常安全的undefined值。上面的代码将改变测试数组。如果你想保持测试数组原样,你可能更喜欢像 a1.slice().reduce... 这样调用。

正如我在评论中所说,如果您正在寻找效率,您可以通过递归来实现:

function findMissing(arr) {
    if (arr.length === 1) return;
    if(arr[1] - arr[0] !== 1){
        return arr[0];
    }
    else{
        return findMissing(arr.slice(1,arr.length));
    }
}

甚至使用 while 循环:

function findMissing(arr) {
    var i = 0;
    while (arr[i+1] - arr[i] === 1) {
        i++;
    }
    if (i < arr.length-1) return arr[i];
}