简体   繁体   English

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

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

I'm trying to use the reduce() method to find one skipped (missing) number in an array of (sometimes almost) consecutive numbers.我正在尝试使用reduce()方法在一组(有时几乎是)连续数字中找到一个跳过(缺失)的数字。 Only one number will be missing at most.最多只会丢失一个数字。 This is my codepen: http://codepen.io/PiotrBerebecki/pen/zBrRVd这是我的代码笔: http ://codepen.io/PiotrBerebecki/pen/zBrRVd

For example,例如,
findMissing([1,2,3,5]) should return 4 findMissing([1,2,3,5])应该返回 4

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

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

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

The code that I developed seems to work fine if there is indeed a number that was skipped.如果确实有一个数字被跳过,我开发的代码似乎可以正常工作。 But it returns an undesired value if all numbers are present.但如果所有数字都存在,它会返回一个不需要的值。 Would you know how to fix it?你知道如何解决吗?

My JS code:我的 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])   );

UPDATE 1:更新 1:

Based on the answers below, the following code delivers the desired outcome using the reduce() method:根据以下答案,以下代码使用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

Your reduce closure/callback function needs to return the value to be used as the next prev in the next iteration.您的 reduce 闭包/回调函数需要返回在下一次迭代中用作下一个prev的值。

Because of this, in the second example, the first iteration returns undefined , as it does not enter the if block.因此,在第二个示例中,第一次迭代返回undefined ,因为它没有进入if块。 The second iteration is passed the parameters of undefined, 3 , where undefined - 3 !== 1 so it returns 2.第二次迭代传递了undefined, 3的参数,其中undefined - 3 !== 1所以它返回 2。

This propagates the way up your iterations, until it returns 3.这会沿着迭代向上传播,直到它返回 3。

As such, I'm struggling to think of a way your reduce function could be adapted to correct this.因此,我正在努力想一种方法可以调整您的reduce函数来纠正这个问题。

Perhaps using a simple for loop might be a bit more robust?也许使用简单for循环可能更健壮一些?

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

Instead of reduce you should use for loop here而不是 reduce 你应该在这里使用for循环

 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]));

I would do this job as follows;我将按以下方式完成这项工作;

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

Note: void 0 is a very safe undefined value in JS.注意: void 0在 JS 中是一个非常安全的undefined值。 The above code will mutate the tested array.上面的代码将改变测试的数组。 You might prefer to call like a1.slice().reduce... if you want to keep the tested array as it is.如果您想保持测试数组保持原样,您可能更喜欢调用a1.slice().reduce...

As I said in comments, if you are looking for efficiency you could do it with recursion:正如我在评论中所说,如果您正在寻找效率,您可以通过递归来做到这一点:

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

Or even with a while loop:甚至有一个while循环:

function findMissing(arr) {
    var i = 0;
    while (arr[i+1] - arr[i] === 1) {
        i++;
    }
    if (i < arr.length-1) return arr[i];
}
 var findMissing = function (list) {  
           var expected_sum = (list[0] + list[list.length - 1]) * (list.length + 1) / 2;
           var sum = list.reduce((a,b)=>a+b);
           return expected_sum - sum;
         }
          
          console.log(findMissing([-5,-1,1,3,5,7,9,11]))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM