bigData
bigData

Reputation: 1318

get sub array of array javascript

I have a array in javascript and I want a sub array of the array with element which are at position n*3, n=0,1,2.. for example if:

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

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

Edit : any soln without looping.

Upvotes: 0

Views: 1829

Answers (4)

Michael Geary
Michael Geary

Reputation: 28850

Here's a solution with no loop:

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]

Simple, isn't it? And not a loop in sight.

Ah, but you ask, "What's the catch? You haven't implemented that pickInterval() function, have you? I bet there's a loop in it."

And you're right. Even if we write our pickInterval() function using some other function that doesn't look like a loop, that function will have a loop in it. And if that one just calls yet another function, eventually you will find a loop.

It may be turtles all the way down, but there's a loop underneath them all.

So, to implement pickInterval(), we could use either approach from @dystroy's answer. We can put the loop right inside the function:

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

Or we can use .filter():

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

Of course there's still a loop here, down inside .filter(). It's just been hidden from us in the very same way that pickInterval() hides any loop from its caller.

And that's the real point. Use .filter(), use a for loop, use whatever you want, as long as you encapsulate it inside a function. Then the inner workings of that function don't matter so much. If you like the for loop because it's fast and easy to understand, use that. If you like the filter() version because it's interesting and elegant, use that. If you later need to use it on a very large array and it's running slow, you can replace it with the for loop version without affecting the code that uses pickInterval().

Whatever code you write for this or for something like it, don't put it inline. Make a function.

Upvotes: 0

dandavis
dandavis

Reputation: 16726

just for kicks, i searched for a way to actually do it without a loop like the OP wanted. without using a loop, it's tough. the closest i could manage gets the right numbers, but converts them to Strings instead of numbers.

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

if you need strong numbers, it's easy, but i am not sure if adding .map(Number) after .split(",") would constitute a loop in your book, but this is the only version that actually finds the desired results without a loop.

this also only works on positive integers as coded.

again, more for fun than something i would recommend using; don't be afraid of loops...

Upvotes: 0

Travis J
Travis J

Reputation: 82287

In order to operate on a set of data of size n, m times, where m > 1, how would you avoid iteration? Really, there is no way unless you use a set of O(1) operations like this:

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

Here is a structural recursion (which can be represented by a loop, and does technically loop).

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

To note: a straight for loop will always be faster. In an expansion of @dystroy's jsperf, this recursion ran slower than the for loop, but faster than the filter. http://jsperf.com/looporfilter/2

Upvotes: 0

Denys S&#233;guret
Denys S&#233;guret

Reputation: 382150

Here's an example of a fancy way :

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

But a simple loop would have been as good (and would have been compatible with IE8). note that filter, even if it's not visible, does loop over the array. You can't avoid a loop (at least for an arbitrary sized array) even if you may disguise it.


Here's how you would do it with a standard loop :

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

Performance is rarely a concern on such operations client side but you might find important to know that the for loop is much faster here : http://jsperf.com/looporfilter

Upvotes: 7

Related Questions