如何使用Javascript删除数组中的所有奇数?

时间:2013-08-19 01:53:45

标签: javascript

有人可以调试此代码吗?我不能为我的生活找到(运行时)错误:

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]

我要发疯了什么的。出于某种原因,所有奇数都没有删除。但正如你在最后看到的那样,它完美无缺。我不知道发生了什么。

5 个答案:

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