Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
434 views
in Technique[技术] by (71.8m points)

algorithm - Tersest way to create an array of integers from 1..20 in JavaScript

What would be the tersest way to create this array:

var x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
         11, 12, 13, 14, 15, 16, 17, 18, 19, 20];

For example, a for loop:

var x = [];
for (var i=1;i<=20;i++) {
  x.push(i);
}

Or a while loop:

var x = [], i = 1, endInt = 20;
while (i <= endInt) {
  x.push(i);
  i++;
}

Would there be other examples that would be terser -- in other words -- less code? I'm thinking of things like in Ruby where the equivalent code I believe would be as simple as 1..20. I'm not aware of syntax like that in JavaScript but I'm wondering if there are shorter ways to do that same thing.

UPDATE: I wasn't thinking of removing semicolons or var for answers in the question, but I have to admit the question implies that. I am more curious about algorithms than shaving bytes. Sorry if I was unclear! Also, making it into a function is simple enough, just slap function range(start, end) { /* guts here */ } around it and you're there. The question is are there novel approaches to the "guts."

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Favorite method

Update Sep13,2015:

Just came up with this new method which works with browsers which support the ES6 standard:

> Array(5).fill().map((x,i)=>i)
[0, 1, 2, 3, 4]

Note the above does a tiny bit of extra work (fills with undefined) but is relatively minor vis-a-vis the speedup you can achieve by using a for loop, and if you forget the .fill you may be confused why your array is mysteriously [empty x 5]. You can encapsulate the above as a custom function, or alternatively use a somewhat more intended method:

> Array.from(Array(5),(x,i)=>i)
[0, 1, 2, 3, 4]

You can of course directly go from that into whatever you want to do, like python's list comprehensions e.g. [i**2 for i in range(5)]:

> Array.from(Array(5), (_,i)=> i**2)
[0, 1, 4, 9, 16]

... or if you want to get more complicated...:

> Array.from(Array(5), (_,i)=> {
    const R = /*some computation*/;
    return /*etc*/;
});

[edit May,2021]: theoretically tersest way of defining such a function nowadays is f=i=>i?[...f(i-1),i]:[], where you replace f with range1 or whatever the name is, but which would be very slow (quadratic complexity) due to intermediate structures so should never be used. f=i=>i?f(i-1)&&x.push(i)&&x:x=[] is linear complexity but relies on abuse of notation and is unreadable and pollutes global variables as well. But, since defining arrow functions (which don't bind but rather inherit this) is pretty terse nowadays, you could just wrap the above solution:

const range1 = n=> Array.from(Array(n), (_,i)=> i+i);
// range1(5)==[1, 2, 3, 4, 5]

everything below is historical:

After thinking about it a bit, this is the shortest implementation of the standard range(N) function in JavaScript I could come up with:

function range1(i){return i?range1(i-1).concat(i):[]}

Note: Do not use this in production; it's O(N^2)

Contrast with current top-voted answer:

function range1(i){var x=[];var i=1;while(x.push(i++)<i){};return x}

Example:

> range1(5)
[1, 2, 3, 4, 5]

This is like the poster child for recursion, though I was expecting it to be longer until I thought of ternary-if-statement, which brings it down to 42 necessary characters.

Note that the "standard" range function returning [start,end) can be written by doing .concat(i-1).


Update: Ooh, I discovered an incredibly short version with ugly imperative syntax by abusing for loops, reverse-ordering, the fact that assignments return a value: for(y=[],i=20;y[--i]=i;){} consisting of only 25 characters (though you will want var y which you can insert into a for loop, and +1 if you don't want 0...19). While it is not shorter if you need to define a function, it is shorter than i?r(i-1).concat(i):[] if you do not need to make a function.


Added some performance profiling testcases: it seems that everything besides a standard in-order for-loop is 10x slower, at least on V8. https://jsperf.com/array-range-in-javascript (Of course, none of this matters if you're programming in a functional style anyway and would hit every element with a function call anyway.)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...