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?

user2402616
  • 1,434
  • 4
  • 22
  • 38
  • 2
    Efficiency comes when you have a bottleneck and here you are trying do a micro-optimization which won't make any noteable difference. – nice_dev Aug 20 '20 at 19:16
  • 2
    `[...Array(10).keys()].map(String)` or `Object.keys(Array(10).fill())` – marzelin Aug 20 '20 at 20:11

4 Answers4

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.

trincot
  • 317,000
  • 35
  • 244
  • 286
  • 2
    This kind of breaks at 10 though, but if 0-9 was the only requirement its not so bad. – Travis J Aug 20 '20 at 19:41
  • 1
    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. – trincot Aug 20 '20 at 19:50
  • 2
    this is the canonical answer ... – Nina Scholz Aug 20 '20 at 20:22
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']
101arrowz
  • 1,825
  • 7
  • 15
1

Try:

console.log(Array(20).fill().map((_, i) => String(i + 1)));
PotatoParser
  • 1,008
  • 7
  • 19
1

You could spread a number.

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

console.log([...10]);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • 1
    But now you cannot spread numeric types any more... Changing the Number prototype seems a bad idea, as it affects all other code. – trincot Aug 20 '20 at 20:42