0

我在javascript中有一个数组,我想要一个数组的子数组,其中元素位于n * 3,n = 0,1,2 ..例如,如果:

var arr = [1,2,3,4,5,6,7,8,9,10,11,12]

var subArr = [1,4,7,10]

编辑:任何没有循环的解决方案。

4

4 回答 4

6

这是一个奇特方式的示例:

var brr = [1,2,3,4,5,6,7,8,9,10,11,12].filter(function(_,i){ return !(i%3) })

但是一个简单的循环也一样好(并且与 IE8 兼容)。请注意filter,即使它不可见,它也会数组上循环。即使您可以伪装它,您也无法避免循环(至少对于任意大小的数组)。


以下是使用标准循环的方法:

var brr = [];
for (var i=0; i<arr.length; i+=3) brr.push(arr[i])

在此类操作客户端上,性能很少是一个问题,但您可能会发现知道for循环在这里要快得多:http: //jsperf.com/looporfilter

于 2013-07-12T20:48:05.223 回答
0

为了对一组大小为 n、m 次的数据进行操作,其中 m > 1,您将如何避免迭代?真的,除非你使用这样的一组 O(1) 操作,否则没有办法:

var arr = [1,2,3,4,5,6,7,8,9,10,11,12];
var subarr = [];
subarr.push(arr[0]);
subarr.push(arr[3]);
subarr.push(arr[6]);
subarr.push(arr[9]);

这是一个结构递归(可以用循环表示,并且在技术上是循环)。

var arr = [1,2,3,4,5,6,7,8,9,10,11,12];
var subarr = [];
(function recur(n){
 if( n >= arr.length ) return;
 subarr.push(arr[n]);
 recur(n+3);
})(0);

注意:直接的 for 循环总是更快。在 @dystroy 的 jsperf 的扩展中,此递归的运行速度比 for 循环慢,但比过滤器快。http://jsperf.com/looporfilter/2

于 2013-07-12T21:39:03.667 回答
0

只是为了好玩,我寻找一种方法来实际做到这一点,而无需像 OP 想要的那样循环。不使用循环,这很难。我能管理的最接近的得到正确的数字,但将它们转换为字符串而不是数字。

var r=[1,2,3,4,5,6,7,8,9,10,11,12,13,14];
alert(   "".replace.call(r+",-0,-0,-0", /(\d+),\d+,?(\d+,|$)/g, "$1,")
           .replace(/(,?\-0){1,4}$/g,"")
           .split(",")    ); 
 //shows: 1,4,7,10,13

如果您需要强数字,这很容易,但我不确定在 .split(",") 之后添加 .map(Number) 是否会在您的书中构成一个循环,但这是唯一真正找到所需结果的版本一个循环。

这也仅适用于编码的正整数。

再次,比我推荐使用的东西更有趣;不要害怕循环...

于 2013-07-12T21:50:14.633 回答
0

这是一个没有循环的解决方案:

var arr = [1,2,3,4,5,6,7,8,9,10,11,12];
// pickInterval is a function that automatically picks every "n"
// elements from an array, starting with the first element
var subArr = pickInterval( arr, 3 );
// now subArr is [1,4,7,10]

很简单,不是吗?而且看不到一个循环。

啊,但是你问,“有什么问题?你还没有实现那个pickInterval()功能,是吗?我敢打赌它里面有一个循环。”

你是对的。即使我们pickInterval()使用其他看起来不像循环的函数来编写我们的函数,函数也会有一个循环。如果那个只是调用另一个函数,最终你会发现一个循环。

它可能一直是海龟,但它们下面都有一个循环。

因此,要实现pickInterval(),我们可以使用@dystroy 回答中的任何一种方法。我们可以将循环放在函数内部:

function pickInterval( array, interval ) {
    var result = [];
    for( var i = 0, n = array.length;  i < n;  i += 3 )
        result.push( array[i] );
    return result;
}

或者我们可以使用.filter()

function pickInterval( array, interval ) {
    return array.filter( function( _, i ){
        return !( i % 3 );
    });
}

当然这里还有一个循环,在里面.filter()。它只是对我们隐藏起来,就像对pickInterval()调用者隐藏任何循环一样。

这才是真正的重点。使用.filter(),使用for循环,使用任何你想要的,只要你将它封装在一个函数中。那么该函数的内部工作原理就无关紧要了。如果您喜欢for循环,因为它快速且易于理解,请使用它。如果您喜欢这个filter()版本,因为它有趣且优雅,请使用它。如果您以后需要在一个非常大的数组上使用它并且它运行缓慢,您可以将其替换为for循环版本,而不会影响使用 pickInterval().

无论您为此或类似的东西编写什么代码,都不要将它内联。做一个函数。

于 2013-07-12T22:41:57.453 回答