How to generate sequence of numbers/chars in javascript?

Viewed 99318

Is there a way to generate sequence of characters or numbers in javascript?

For example, I want to create array that contains eight 1s. I can do it with for loop, but wondering whether there is a jQuery library or javascript function that can do it for me?

22 Answers

One liner:

new Array(10).fill(1).map( (_, i) => i+1 )

Yields:

[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]

This is the simplest one by far

const sequence = [...Array(10).keys()]
console.log(sequence)

Output : [0,1,2,3,4,5,6,7,8,9]

range(start,end,step): With ES6 Iterators

You can easily create range() generator function which can function as an iterator. This means you don't have to pre-generate the entire array.

function * range ( start, end, step ) {
  let state = start;
  while ( state < end ) {
    yield state;
    state += step;
  }
  return;
};

Now you may want to create something that pre-generates the array from the iterator and returns a list. This is useful for functions that accept an array. For this we can use Array.from()

const generate_array = (start,end,step) => Array.from( range(start,end,step) );

Now you can generate a static array easily,

const array = generate_array(1,10,2);

But when something desires an iterator (or gives you the option to use an iterator) you can easily create one too.

for ( const i of range(1, Number.MAX_SAFE_INTEGER, 7) ) {
  console.log(i)
}

Here's a benchmark where the comment after each option shows the median time of a thousand runs in ms:

let opt=[
  'Array(n).fill().map((_,i)=>i)', // 2.71
  'Array(n).fill().map(function(_,i){return i})', // 2.73
  'let o=[];for(let i=0;i<1e5;i++)o[i]=i', // 3.29
  'let o=[];for(let i=0;i<1e5;i++)o.push(i)', // 3.31
  'let o=[];for(let i=0,n2=n;i<n2;i++)o[i]=i', // 3.38
  'let o=[];for(let i=0;i<n;i++)o[i]=i', // 3.57
  'Array.apply(null,Array(n)).map(Function.prototype.call.bind(Number))', // 3.64
  'Array.apply(0,Array(n)).map((_,i)=>i)', // 3.73
  'Array.apply(null,Array(n)).map((_,i)=>i)', // 3.77
  'o2=[];for(let i=0;i<n;i++)o2[i]=i', // 4.42
  '[...Array(n).keys]', // 7.07
  'Array.from({length:n},(_,i)=>i)', // 7.13
  'Array.from(Array(n),(_,i)=>i)', // 7.23
  'o3=[];for(i3=0;i3<n;i3++)o3[i3]=i3' // 24.34
]

let n=1e5
opt.sort(()=>Math.random()-.5)
for(let opti of opt){
  let t1=process.hrtime.bigint()
  eval(opti)
  let t2=process.hrtime.bigint()
  console.log(t2-t1+'\t'+opti)
}

The for loop became a lot faster when I used block-scoped variables instead of global variables.

I used median time instead of mean because occasionally a single run can take much longer than typical runs which distorts the mean time.

I ran the benchmark like for i in {1..1000};do node seqbench.js;done, because when I invoked the script only once but I ran each option 1000 times inside the script, it was affected by some kind of an optimization where the for loops became the fastest options.

If like me you use linspace a lot, you can modify your version of linspace easily like so:

function linSeq(x0, xN) {
    return linspace(x0, xN, Math.abs(xN-x0)+1);
}

function linspace(x0, xN, n){

    dx = (xN - x0)/(n-1);
    var x = [];
    for(var i =0; i < n; ++i){
        x.push(x0 + i*dx);
    }

    return x;
}

You can then use linSeq in any direction, e.g. linSeq(2,4) generates 2,3,4 while linSeq(4,2) generates 4,3,2.

Another method, for those how are memory saving pedant:

Array.apply(null, Array(3)).map(Function.prototype.call.bind(Number))
var GetAutoNumber = exports.GetAutoNumber = (L) => {
    let LeftPad = (number, targetLength) => {
        let output = number + '';
        while (output.length < targetLength) {
            output = '0' + output;
        }
        return output;
    }
    let MaxNumberOfGivenLength = "";
    for (let t = 0;t < L;t++) {
        MaxNumberOfGivenLength = MaxNumberOfGivenLength + "9"
    }
    let StartTime = +new Date();
    let Result = [];
    let ReturnNumber;
    for (let i = 1;i <= MaxNumberOfGivenLength;i++) {
        Result.push(LeftPad(i, L))
    }
    for (let k = 0;k != 26;k++) {
        for (let j = 0;j <= 999;j++) {
            Result.push(String.fromCharCode(k + 65) + LeftPad(j, (L - 1)));
        }
    }
    console.log(Result.length)
    return Result;
}
GetAutoNumber(3)

It will generate result like 001-999, A01-A99... Z01-Z99

If you want to produce a sequence of equal numbers, this is an elegant function to do it (solution similar to other answer):

seq = (n, value) => Array(n).fill(value)

If you want to produce a sequence of consecutive numbers, beginning with 0, this a nice oneliner:

seq = n => n<1 ? [] : [...seq(n-1), n]

This is for different start values and increments:

seq2 = (n, start, inc) => seq(n).map(i => start + inc * i)

Javascript ES6 in action :)

Array(8).fill(1)

console.log(Array(8).fill(1))

in ES6 simple solution:

seq = (from, len, step = 1) => Array.from({length: len}, (el, i) => from + (i * step));

Generating an integer sequence is something that should definitely be made more convenient in JavaScript. Here is a recursive function returns an integer array.

function intSequence(start, end, n = start, arr = []) {
  return n === end ? arr.concat(n)
    : intSequence(start, end, start < end ? n + 1 : n - 1, arr.concat(n));
}

$> intSequence(1, 1)
<- Array [ 1 ]

$> intSequence(1, 3)
<- Array(3) [ 1, 2, 3 ]

$> intSequence(3, -3)
<- Array(7) [ 3, 2, 1, 0, -1, -2, -3 ]
Related