2

I was just starting with codewars challenges, one of them is "Generate range of integers" problem. I managed to solve problem with for loop, but i was wondering if i could solve this problem in one line?

I have tried using fill and map methods combined with while and do-while loops. The problem is I am unable get the first number (starting min) inside my returned array. The first time while loop evaluates to true, it returns minimum incremented by step value.

function generateRange(min,max,step) {
        return Array(Math.floor((max - min) / step ))
                    .fill()
                    .map(() => {while(min <= max) {return min+=step;}});
    }
    
console.log(generateRange(0, 10, 2));

I was expecting number from min to max, with step within them. min = 0, max = 10, step = 2, result => [0,2,4,6,8,10] but i get all the numbers without the first starting minimum [2,4,6,8,10].

Nick Parsons
  • 45,728
  • 6
  • 46
  • 64
Tandy
  • 31
  • 1
  • 3
  • 1
    why is there a while loop inside of the map call. Make no sense – epascarello Sep 18 '19 at 13:02
  • You are going to have an off by one error with your logic since you are including the start and end. – epascarello Sep 18 '19 at 13:06
  • 1
    from mdn [Sequence generator (range)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from#Sequence_generator_(range)) – User863 Sep 18 '19 at 13:11
  • Possible duplicate of [Does JavaScript have a method like "range()" to generate a range within the supplied bounds?](https://stackoverflow.com/questions/3895478/does-javascript-have-a-method-like-range-to-generate-a-range-within-the-supp) – Nick Parsons Sep 18 '19 at 13:24

6 Answers6

4

You could decrement min by one step and take this value for further mapping.

function generateRange(min, max, step) {
    return Array.from(
        { length: Math.floor((max - (min -= step)) / step) },
        () => min += step
    );
}

console.log(generateRange(0, 10, 2));
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
2

Sticking close to your original code:

function generateRange(min,max,step) {
return Array(Math.floor((max - min + step) / step ))
             .fill()
             .map(() => {while(min <= max) {return (min+=step)-step;}});
}
console.log(generateRange(0, 10, 2));
Scott Hunter
  • 48,888
  • 12
  • 60
  • 101
1

Something like this should work:

function range(min,max,step = 1) {
   return [...Array(Math.floor((max-min+step)/step)).keys()].map(x => x*step + min);
}

console.log(range(0,10,2))
console.log(range(2,5,1))
console.log(range(1,25,5))
console.log(range(0,100,10))
Terry Lennox
  • 29,471
  • 5
  • 28
  • 40
1

function generateRange(min, max, step) {
  return "0".repeat(Math.floor((max - min) / step) + 1).split("").map((x, i) => min + i * step);
}

console.log(generateRange(0, 10, 2));
nick zoum
  • 7,216
  • 7
  • 36
  • 80
1

This should work:

function generateRange(min,max,step) {
  return Array.from(Array(((max - min) / step) + 1).keys()).map(el => (el * step) + min);
}
console.log(generateRange(20, 40, 2));
matrixersp
  • 535
  • 5
  • 17
1

I think generator functions are nice for these type of things.

Your question asks for a one-liner, although I think it looks way nicer as 2 functions. This is because you could use the generator in other places that you might not require an array.

function* iter_generateRange(min,max,step) {
  for (let l = min; l <= max; l += step) yield l;
}

function generateRange(...args) {
 return Array.from(iter_generateRange(...args));
}

const generateRange1liner = (min, max, step) =>
  [...(function* () {
    for (let l = min; l <= max; l += step) yield l;
  }())]; 


//use the generateRange that returns the array
console.log(JSON.stringify(generateRange(10, 20, 2)));

//we can use it here too..
for (const r of iter_generateRange(3, 9, 3)) console.log(r);

//and finally using the 1 liner version
console.log(JSON.stringify(generateRange1liner(10, 20, 2)));
Keith
  • 22,005
  • 2
  • 27
  • 44