有人可以调试此代码吗?我不能为我的生活找到(运行时)错误:
function generate_fibonacci(n1, n2, max, out){
var n = n1+n2;
if(n<max){
out.push(n);
generate_fibonacci(n2, n, max, out);
}
}
function generate_fibonacci_sequence(max){
var out = [1];
generate_fibonacci(0, 1, max, out);
return out;
}
function remove_odd_numbers(arr){
for (var i = 0; i < arr.length; i++) {
if(!(arr[i]%2==0)){
arr.splice(i, 1);
}
}
return arr;
}
function sum(array){
var total = 0;
for (var i = 0; i < array.length; i++) {
total+=array[i];
}
return total;
}
var fib_sq = generate_fibonacci_sequence(4000000);
console.log("Before: " + fib_sq);
remove_odd_numbers(fib_sq);
console.log("After: " + fib_sq);
console.log("WTH?: " + remove_odd_numbers([1,2,3,4,5,6,7,8,9]));
输出:
Before: 1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368,75025,121393,196418,317811,514229,832040,1346269,2178309,3524578
After: 1,2,5,8,21,34,89,144,377,610,1597,2584,6765,10946,28657,46368,121393,196418,514229,832040,2178309,3524578
WTH?: 2,4,6,8
[Finished in 0.3s]
我要发疯了什么的。出于某种原因,所有奇数都没有删除。但正如你在最后看到的那样,它完美无缺。我不知道发生了什么。
答案 0 :(得分:8)
原始代码中的问题是当你删除索引0处的第一个1
时,数组会被移位;现在arr[i]
包含第二个1
;但你只是跨过它。
您需要使用while而不是在此处,或复制到单独的列表。这是拼接的一个例子:
function remove_odd_numbers1(arr){
for (var i = 0; i < arr.length; i++) {
// here
while (arr[i] % 2) {
arr.splice(i, 1);
}
}
return arr;
}
但它会很慢。最好创建一个新阵列:
function remove_odd_numbers2(arr){
var rv = [];
for (var i = 0; i < arr.length; i++) {
if (! (arr[i] % 2)) {
rv.push(arr[i]);
}
}
return rv;
}
一般来说,最好的算法是使用相同的数组,如果不需要原始数据,那么就不需要额外的内存(虽然在javascript上这有点值得怀疑):
function remove_odd_numbers3(arr){
var out = 0;
for (var i = 0; i < arr.length; i++) {
if (! (arr[i] % 2)) {
arr[out++] = arr[i];
}
}
arr.length = out;
return arr;
}
请注意,与拼接算法不同,它在O(n)
时间内运行。
另外,Array.prototype.filter()也不错,是内置的。它还创建了一个新数组,因此可与2进行比较。
答案 1 :(得分:2)
我不确定这一点,但是我怀疑使用splice
与创建新数组相比是有效的。
function remove_odd_numbers(arr) {
var notOdd = [],
i = 0,
len = arr.length,
num;
for (; i < len; i++) {
!((num = arr[i]) % 2) && notOdd.push(num);
}
return notOdd;
}
编辑:您应该使用@Jack建议的本地filter
函数。我把这个答案作为参考。
答案 2 :(得分:2)
这是一种非常简单,快速的方法。使用您的数据,只需48毫秒即可完成。希望这会有所帮助..
function noOdds(values){
return values.filter(function (num) {
return num % 2 === 0;
});
}
答案 3 :(得分:1)
因为splice()
修改了数组,所以索引将在下一次迭代中关闭;你需要减少循环变量,使用像Antti proposed这样的while
循环,或者像Crazy Train mentioned那样向后迭代。
也就是说,使用splice()
很难处理,因为它会就地修改数组。使用filter函数也可以轻松完成此功能:
function remove_odd_numbers(arr)
{
return arr.filter(function(value) {
return value % 2 == 0;
});
}
这将创建并返回仅包含偶数值的新数组。
鉴于此功能的新近性,请检查compatibility section如何处理浏览器IE&lt; 9.许多流行的库,如jQuery,下划线等,为您解决这个问题。
<强>更新强>
不是在之后过滤数组,而是在执行递归时仅添加偶数值会更有效:
function generate_fibonacci(previous, current, max, callback)
{
var next = previous + current;
if (next < max) {
callback(next);
generate_fibonacci(current, next, max, callback);
}
}
function generate_fibonacci_sequence(max, callback)
{
callback(1);
callback(1);
generate_fibonacci(1, 1, max, callback);
}
var out = [];
generate_fibonacci_sequence(4000000, function(value) {
if (value % 2 == 0) {
out.push(value);
}
});
我没有传递out
数组,而是在生成新的序列值时传递一个函数来调用;过滤在回调中完成。
答案 4 :(得分:0)
ES4版本来自&#34; Tabetha Moe&#34;答案
function noOdds(arr) {
return arr.filter(value => value % 2 === 0);
}