0

I want to create an array of digits. I'm currently just hardcoding it as such

const digitGeneration = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];

I know in other languages I can create an array using the range operator for ints. I was hoping I could do something like that in JS. Instead, I came up with this

const digitGeneration = [...Array(10).keys()].map(digit => digit.toString());

Anyone have a simpler way? Or is it not worth it and better to just hardcode it and save execution time for efficiency?

2
  • 2
    Efficiency comes when you have a bottleneck and here you are trying do a micro-optimization which won't make any noteable difference. Commented Aug 20, 2020 at 19:16
  • 2
    [...Array(10).keys()].map(String) or Object.keys(Array(10).fill()) Commented Aug 20, 2020 at 20:11

4 Answers 4

3

You can use spread on a string:

[..."0123456789"]

If you need more numbers (with more digits), then I would go for Array.from, using its callback argument, and mapping with String:

Array.from({length: 20}, (_, i) => String(i+1));

If you would execute this millions of times, then nothing will beat the original hard-coded array literal. But for other "normal" uses, this is quite acceptable.

Sign up to request clarification or add additional context in comments.

3 Comments

This kind of breaks at 10 though, but if 0-9 was the only requirement its not so bad.
The OP wrote "array of digits", and title says "all digit strings", so I don't see how this means arrays of multi-digit numbers. Anyway I added the solution I would use for multi-digit numbers.
this is the canonical answer ...
2

With JavaScript, unless you're building a CPU-intensive library or a function that will be called thousands of times per second, microoptimizations are pointless. I prefer clarity to code length, so I would probably do it like this:

const digitGeneration = Array(10);
for (let i = 0; i < 10; ++i) {
  digitGeneration[i] = i.toString();
}

The way you did it is perfectly fine, though. I suppose if you wanted a general purpose range() like in python, you could create a generator:

function* range(startVal, endVal, step = 1) {
  const stepSign = Math.sign(step);
  if (stepSign === 0) {
    throw new TypeError('step cannot be 0');
  }
  if (arguments.length == 0) {
    throw new TypeError('no range specified');
  }
  if (arguments.length == 1) {
    endVal = startVal;
    startVal = 0;
  }
  for (let i = startVal; Math.sign(endVal - i) === stepSign; i += step) {
    yield i;
  }
}

Since no array is created, for iteration purposes this is as efficient as a for loop, even for massive ranges.

for (const value of range(10000, 1, -1)) {
  console.log(value);
}
// Outputs 10000...2 separated by newline without taking 10KB of memory

Or you could create an array, like you're trying to do:

const digitGeneration = [...range(10)].map(e => e.toString());
// This is ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']

1 Comment

The range iterator is certainly going to be very efficient.
1

Try:

console.log(Array(20).fill().map((_, i) => String(i + 1)));

Comments

1

You could spread a number.

Number.prototype[Symbol.iterator] = function* () {
    for (var i = 0; i < this; i++) yield i.toString();
};

console.log([...10]);

1 Comment

But now you cannot spread numeric types any more... Changing the Number prototype seems a bad idea, as it affects all other code.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.