0

I implemented the way to generate a list of items with iterable counts with prefix 0. What is the best way to generate such kind of list?

Current behaviour:

const generateList = (length, n, i) => {
let b = n+i

return b.toString().padStart(length.toString().length + n.toString.length, 0)
}

Array(10).fill(null).map((x, i) => generateList(10,2, i))

Output result:

["002", "003", "004", "005", "006", "007", "008", "009", "010", "011"]

Do u have any idea to make it another way?

Hyyan Abo Fakher
  • 3,207
  • 3
  • 18
  • 32
Palaniichuk Dmytro
  • 2,041
  • 3
  • 26
  • 53

3 Answers3

2

You could determine the number of characters needed at the start and used the predetermined value to format the output for the array.

function createList(startValue, endValue) {
  let 
    // The minimum output length, for a single digit number, is 2 chars.
    outputLength = 2,
    testValue = 10,
    // Create an empty array which has as many items as numbers we need to
    // generate for the output. Add 1 to the end value as this is to be 
    // inclusive of the range to create. If the +1 is not done the resulting 
    // array is 1 item too small.
    emptyArray = Array(endValue - startValue + 1);
    
  // As long as test value is less than the end value, keep increasing the 
  // output size by 1 and continue to the next multiple of 10.
  while (testValue <= endValue) {
    outputLength++;
    testValue = testValue * 10;
  }
  
  // Create a new array, with the same length as the empty array created
  // earlier. For each position place a padded number into the output array.
  return Array.from(emptyArray, (currentValue, index) => {
    // Pad the current value to the determined max length.
    return (startValue + index).toString().padStart(outputLength, '0');
  });
}

function createListWithLength(length, startValue = 0) {
  return createList(startValue, startValue + length);
}

console.log(createList(2,10));
console.log(createListWithLength(30));
console.log(createListWithLength(10, 995));
Thijs
  • 2,281
  • 2
  • 12
  • 21
  • the parens are redundant here -> `(endValue + 1) - startValue` – marzelin Sep 10 '18 at 14:28
  • 1
    and use `Array.from(Array(length), fillerFn)` instead filling with `null`s and then mapping over. – marzelin Sep 10 '18 at 14:29
  • Yeah, I have a things with adding parenthesis where not absolutely necessary. I guess I find it easier to read. I'd actually prefer a good old `for`-loop, have the feeling it would give better performance. – Thijs Sep 10 '18 at 14:31
  • Didn't know about that second param for the `Array.from` method, thanks! – Thijs Sep 10 '18 at 14:32
  • I prefer `for..of` cause it can work with iterables (i.e. node lists) – marzelin Sep 10 '18 at 14:32
  • `Array.from(emptyArray)` doesn't really make much sense. I recommend to use `Array.from({length})`, as only the length is important here – Bergi Sep 10 '18 at 14:53
  • This `while` loop is essentially just computing the `Math.log10(endValue)`? – Bergi Sep 10 '18 at 14:54
  • Yeah, that's what the `while` does. Didn't know there is a Math method that basically does the same thing. I used `emptyArray` instead of `Array(end-start+1)` is I felt it increased the readability. – Thijs Sep 10 '18 at 14:57
1

Have a look at generators:

function* range(from, to) {
  for (var i=from; i<to; i++)
    yield i;
}
function* paddedRange(from, to) {
  const length = (to-1).toString(10) + 1 /* at least one pad */;
  for (const i of range(from, to))
    yield i.padStart(length, '0');
}

console.log(Array.from(paddedRange(2, 12)));

You can also inline the loop from range into paddedRange, or you can make it return an array directly:

function paddedRange(from, to) {
  const length = (to-1).toString(10) + 1 /* at least one pad */;
  return Array.from(range(from, to), i => i.padStart(length, '0'));
}

console.log(paddedRange(2, 12));

The main simplification is that you should compute the padding length only once and give it a denotative name, instead of computing it for every number again. Also ranges are usually given by their lower and upper end instead of their begin and a length, but you can easily switch back if you need the latter for some reason.

Bergi
  • 513,640
  • 108
  • 821
  • 1,164
  • generators, nice. But I see also good old `var` still used ;) – marzelin Sep 10 '18 at 14:39
  • @marzelin There's no advantage in using `let` here, as we don't need a block scope. – Bergi Sep 10 '18 at 14:40
  • so you prefer `var` over `let`, and use `let` only when needed? – marzelin Sep 10 '18 at 14:42
  • @marzelin I tend use `var` for all function-scoped variables, and `let` when I need a block scope for a closure or don't want to use the variable after the loop. If it doesn't matter (like here) I'll flip a coin or check which side of the bed I got up today :-) – Bergi Sep 10 '18 at 14:45
  • oh sorry, I meant consistent ;) – marzelin Sep 10 '18 at 14:51
0

Not sure, but maybe something like this

const generateList = length => Array(length).fill('0').map((item, index) => item + index);

console.log(generateList(20));
Dexygen
  • 11,681
  • 11
  • 73
  • 144
Art Olshansky
  • 1,379
  • 1
  • 5
  • 16