How to create an array containing 1…N

后端 未结 30 1349
旧时难觅i
旧时难觅i 2020-11-22 01:04

I\'m looking for any alternatives to the below for creating a JavaScript array containing 1 through to N where N is only known at runt

相关标签:
30条回答
  • 2020-11-22 01:48
    function range(start, end) {
        var foo = [];
        for (var i = start; i <= end; i++) {
            foo.push(i);
        }
        return foo;
    }
    

    Then called by

    var foo = range(1, 5);
    

    There is no built-in way to do this in Javascript, but it's a perfectly valid utility function to create if you need to do it more than once.

    Edit: In my opinion, the following is a better range function. Maybe just because I'm biased by LINQ, but I think it's more useful in more cases. Your mileage may vary.

    function range(start, count) {
        if(arguments.length == 1) {
            count = start;
            start = 0;
        }
    
        var foo = [];
        for (var i = 0; i < count; i++) {
            foo.push(start + i);
        }
        return foo;
    }
    
    0 讨论(0)
  • 2020-11-22 01:48

    It seems the only flavor not currently in this rather complete list of answers is one featuring a generator; so to remedy that:

    const gen = N => [...(function*(){let i=0;while(i<N)yield i++})()]
    

    which can be used thus:

    gen(4) // [0,1,2,3]
    

    The nice thing about this is you don't just have to increment... To take inspiration from the answer @igor-shubin gave, you could create an array of randoms very easily:

    const gen = N => [...(function*(){let i=0;
      while(i++<N) yield Math.random()
    })()]
    

    And rather than something lengthy operationally expensive like:

    const slow = N => new Array(N).join().split(',').map((e,i)=>i*5)
    // [0,5,10,15,...]
    

    you could instead do:

    const fast = N => [...(function*(){let i=0;while(i++<N)yield i*5})()]
    
    0 讨论(0)
  • 2020-11-22 01:52

    This is probably the fastest way to generate an array of numbers

    Shortest

    var a=[],b=N;while(b--)a[b]=b+1;
    

    Inline

    var arr=(function(a,b){while(a--)b[a]=a;return b})(10,[]);
    //arr=[0,1,2,3,4,5,6,7,8,9]
    

    If you want to start from 1

    var arr=(function(a,b){while(a--)b[a]=a+1;return b})(10,[]);
    //arr=[1,2,3,4,5,6,7,8,9,10]
    

    Want a function?

    function range(a,b,c){c=[];while(a--)c[a]=a+b;return c}; //length,start,placeholder
    var arr=range(10,5);
    //arr=[5,6,7,8,9,10,11,12,13,14]
    

    WHY?

    1. while is the fastest loop

    2. Direct setting is faster than push

    3. [] is faster than new Array(10)

    4. it's short... look the first code. then look at all other functions in here.

    If you like can't live without for

    for(var a=[],b=7;b>0;a[--b]=b+1); //a=[1,2,3,4,5,6,7]
    

    or

    for(var a=[],b=7;b--;a[b]=b+1); //a=[1,2,3,4,5,6,7]
    
    0 讨论(0)
  • 2020-11-22 01:52

    There is another way in ES6, using Array.from which takes 2 arguments, the first is an arrayLike (in this case an object with length property), and the second is a mapping function (in this case we map the item to its index)

    Array.from({length:10}, (v,i) => i)
    

    this is shorter and can be used for other sequences like generating even numbers

    Array.from({length:10}, (v,i) => i*2)
    

    Also this has better performance than most other ways because it only loops once through the array. Check the snippit for some comparisons

    // open the dev console to see results
    
    count = 100000
    
    console.time("from object")
    for (let i = 0; i<count; i++) {
      range = Array.from({length:10}, (v,i) => i )
    }
    console.timeEnd("from object")
    
    console.time("from keys")
    for (let i =0; i<count; i++) {
      range = Array.from(Array(10).keys())
    }
    console.timeEnd("from keys")
    
    console.time("apply")
    for (let i = 0; i<count; i++) {
      range = Array.apply(null, { length: 10 }).map(function(element, index) { return index; })
    }
    console.timeEnd("apply")

    0 讨论(0)
  • 2020-11-22 01:52

    In ES6:

    Array.from({length: 1000}, (_, i) => i).slice(1);
    

    or better yet (without the extra variable _ and without the extra slice call):

    Array.from({length:1000}, Number.call, i => i + 1)
    

    Or for slightly faster results, you can use Uint8Array, if your list is shorter than 256 results (or you can use the other Uint lists depending on how short the list is, like Uint16 for a max number of 65535, or Uint32 for a max of 4294967295 etc. Officially, these typed arrays were only added in ES6 though). For example:

    Uint8Array.from({length:10}, Number.call, i => i + 1)
    

    ES5:

    Array.apply(0, {length: 1000}).map(function(){return arguments[1]+1});
    

    Alternatively, in ES5, for the map function (like second parameter to the Array.from function in ES6 above), you can use Number.call

    Array.apply(0,{length:1000}).map(Number.call,Number).slice(1)
    

    Or, if you're against the .slice here also, you can do the ES5 equivalent of the above (from ES6), like:

    Array.apply(0,{length:1000}).map(Number.call, Function("i","return i+1"))
    
    0 讨论(0)
  • 2020-11-22 01:52

    You can use Array fill and map from Es6; just like some few people suggested in the answers they gave for this question. Below are some few examples:

    Example-One: Array(10).fill(0).map((e,i)=>i+1)
    
    Result-One: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    
    Example-Two: Array(100/10).fill(0).map((e,i)=>(i*10)+10)
    
    Result-Two:[10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
    
    

    I prefer this because I find it straight forward and easier.

    0 讨论(0)
提交回复
热议问题