Creating a range function in javascript

Hi guys, I'm trying to make a function in javascript that returns an array from a range (start, end), and they are supposed to make an optional argument, which by default is one when it is undefined. I can make this function work when I provide all the arguments, but it returns an empty array when I pass only two arguments. Here is the question:

Write a range function that takes two arguments, start and end, and returns an array containing all the numbers from beginning to end (and including).

Then write a sum function that takes an array of numbers and returns the sum of these numbers. Run the previous program and see if it really returns 55.

As a bonus assignment, modify the range function to accept an additional third argument, which indicates the value of the step used to create the array. If no steps are specified, the array elements are incremented in increments of 1, which corresponds to the old behavior. The range of function call (1, 10, 2) should return [1, 3, 5, 7, 9]. Make sure that it also works with negative pitch values ​​so that the range (5, 2, -1) produces [5, 4, 3, 2].

and here is my code

function range(start, end, increment){ var array = []; var current = start; var counter; if (increment == undefined){ counter = 1; } else { counter = increment; } if (increment > 0){ while(current <= end){ array.push(current); current += counter; } } else if (increment < 0){ while(current >= end){ array.push(current); current += counter; } } return array; } 

can someone explain why its violation? I know that some C # and they used to jump into the debugger in visual studio when something goes wrong as in javascript

+5
source share
4 answers

You can simplify the code a bit and use the increment variable to increase. But first, I suggest checking if the value is false ( 0 , null , undefined , etc.) and assign it 1 .

Not implemented: check if start and end suitable.

 function range(start, end, increment) { var array = []; var current = start; increment = increment || 1; if (increment > 0) { while (current <= end) { array.push(current); current += increment; } } else { while (current >= end) { array.push(current); current += increment; } } return array; } console.log(range(1, 3, 0)); console.log(range(2, 5)); console.log(range(1, 9, 1)); console.log(range(5, 2, -1)); 
+4
source

First you check to see if increment undefined and set counter accordingly, but later you check if (increment > 0){ again. Although this is undefined , none of your cases fit, so nothing happens.

Change your checks to this:

 if (counter > 0){ // ... } else if (counter < 0){ // ... } 
+3
source

A very simple unidirectional (upstream) inclusive range - from x to y increases by 1 each time.

 // range :: (Int, Int) -> [Int] const range = (x,y) => x > y ? [] : [x, ...range(x + 1, y)]; console.log(range(1,4)); // [1,2,3,4] console.log(range(3,3)); // [3] console.log(range(6,3)); // [] 

Small adaptation supporting bi-directional (up or down) range - still increasing or decreasing by 1

 // range :: (Int, Int) -> [Int] const range = (x,y) => { if (x > y) return range(y,x).reverse(); else return x === y ? [y] : [x, ...range(x + 1, y)]; } console.log(range(1,4)); // [1,2,3,4] console.log(range(3,3)); // [3] console.log(range(6,3)); // [6,5,4,3] 

Another adaptation that uses higher-order functions for more control over the range - it gives you the step-by-step / gradual behavior you are looking for - is a more powerful tool because it allows you to use the t function to select the next value.

 const gte = x => y => y >= x; const lte = x => y => y <= x; const add = x => y => y + x; const sub = x => y => y - x; // range :: (Int, (Int -> Bool), (Int -> Int)) -> [Int] const range = (x, p, t) => { if (p(x)) return [x, ...range(t(x), p, t)]; else return []; }; console.log(range(2, lte(8), add(2))); // [2,4,6,8] console.log(range(9, gte(0), sub(3))); // [9,6,3,0] console.log(range(9, gte(0), sub(5))); // [9, 4] // very power. wow. const double = x => x + x; console.log(range(2, lte(50), double)); // [2,4,8,16,32] 

This function has the same risks that are inherent in for and while - it is up to you to make sure that you do not put it in an infinite loop.


functional overload

Warning: esoteric, impractical functionals are ahead. The following information is provided for your academic enjoyment only.

The range function is also one of my favorite demonstrations of the y combinator. Here I will show you two examples.

naive range

 const U = f => f (f); const Y = U (h => f => f (x => h (h) (f) (x))); const range = Y (f => acc => x => y => x > y ? acc : f ([...acc, x]) (x + 1) (y) ) ([]); console.log(range (3) (6)); // [3,4,5,6] console.log(range (6) (6)); // [6] console.log(range (9) (6)); // [] 

and higher range

 const U = f => f (f); const Y = U (h => f => f (x => h (h) (f) (x))); const lt = x => y => y < x; const gt = x => y => y > x; const add1 = x => x + 1; const sub1 = x => x - 1; const range = Y (f => acc => x => p => t => p(x) ? f ([...acc, x]) (t(x)) (p) (t) : acc ) ([]); console.log(range (3) (lt(6)) (add1)); // [3,4,5] console.log(range (6) (lt(6)) (add1)); // [] console.log(range (9) (gt(6)) (sub1)); // [9,8,7] 

What is this beauty.

+2
source

These answers are great. I just wanted to give you an idea of ​​how a more functional approach can solve the problem:

 // auxiliary functions: const append = (x, xs) => xs.concat([x]); const prepend = (x, xs) => [x].concat(xs); // main function const range = (x, y, step, acc = [], op = append) => step && step < 0 ? range(y, x, -step, acc, prepend) : step && x <= y ? range(x + step, y, step, op(x, acc), op) // tail call : acc; console.log(range(1,5,1)); // [1,2,3,4,5] console.log(range(1,5,2)); // [1,3,5] console.log(range(1,5,6)); // [1] console.log(range(5,1,1)); // [] console.log(range(1,5,0)); // [] console.log(range(5,1,-1)); // [5,4,3,2,1] console.log(range(5,1,-2)); // [5,3,1] console.log(range(5,1,-6)); // [1] console.log(range(1,5,-1)); // [] 

Algorithm:

  • acc = [] and op = append default parameter values ​​(accepted if omitted during function call)
  • step && step < 0 , if step is zero, otherwise it is checked whether the step is negative
  • range(y, x, -step, acc, prepend) is called when step is negative and converts the range parameterization so that step can be positive (note that -step equivalent to -(-1) , which evaluates to 1 )
  • range(x + step, y, step, op(x, acc), op) A recursive case, which means that the function calls itself (note that op can be either append or prepend depending on the initial sign of step , that x incremented by step and added / added to acc )
  • acc base register that stops recursion and returns the accumulated array
0
source

All Articles