使用 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];
}
我正在尝试使用 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];
}