在javascript

时间:2016-06-01 12:30:30

标签: javascript

大家好我正在尝试在javascript中创建一个函数,从范围(开始,结束)返回一个数组,并且我应该创建一个可选参数,默认为1时未定义。当我提供所有参数时,我可以使函数工作,但当我只传递两个参数时返回一个空数组。这是一个问题:

  

编写一个范围函数,它接受两个参数,start和end,并返回一个包含从start到(和包括)end的所有数字的数组。

     

接下来,编写一个sum函数,它接受一个数字数组并返回这些数字的总和。运行上一个程序,看它是否确实返回55。

     

作为奖励分配,修改范围函数以采用可选的第三个参数,该参数指示用于构建阵列的“步长”值。如果没有给出步骤,则数组元素以1的增量上升,对应于旧行为。函数调用范围(1,10,2)应返回[1,3,5,7,9]。确保它也适用于负步长值,以便范围(5,2,-1)产生[5,4,3,2]。

这是我的代码

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;
}

有人可以解释为什么它会破裂吗?我知道一些c#和我过去能够在出现问题时跳入Visual Studio中的调试器,这与javascript不同

6 个答案:

答案 0 :(得分:5)

您可以稍微简化代码并使用increment变量进行递增。但在此之前,我建议测试该值是否为假(0nullundefined等),然后将1分配给它。

未实施:请检查startend是否合适。

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));    

答案 1 :(得分:4)

一个非常简单的单向(升序),包含范围 - 每次从x增加到y增加1

// 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)); // []

支持双向(升序降序)范围的轻微调整 - 仍然按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]

使用高阶函数进行更多控制范围的另一个改编 - 这有效地为你提供了一些你正在寻找的步进/递增行为 - 这更强大,因为它允许你使用函数,{{1选择下一个值。

t

此功能与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]for具有相同的风险 - 您可以确保不要将其置于无限循环中。

功能过载

  

警告:未来的神秘,不切实际的功能。以下信息仅供您学术享受。

while函数也恰好是我最喜欢的range组合子演示之一。我将在这里向您展示两个例子。

天真Y

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)); // []

range

这是多么美丽的东西。

答案 2 :(得分:3)

首先检查increment是否未定义并相应地设置counter,但稍后再次检查if (increment > 0){。虽然undefined没有任何案例匹配,但没有任何事情发生。

将支票更改为:

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

答案 3 :(得分:0)

给出的答案很棒。我只是想让你了解一个更实用的方法如何解决这个任务:

// 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)); // []

算法:

  • acc = []op = append默认参数值(如果在函数调用期间省略,则采用)
  • 如果step && step < 0为零,则
  • step短路,否则检查步骤是否为负
  • range(y, x, -step, acc, prepend)为否定时会调用
  • step并转换range的参数化,以便step可以为正(请注意-step是相当于-(-1),评估为1
  • range(x + step, y, step, op(x, acc), op)递归情况,即函数调用自身(注意op可以是appendprepend,具体取决于step的初始符号,x增加step并附加/添加到acc
  • acc基本情况,用于停止递归并返回累积数组

答案 4 :(得分:0)

处理浮点数和负数的非常紧凑的范围函数:

const range = (lower,upper,step)=>{
  return Array.from(new Array(Math.floor(upper/step-lower/step)+1),(_,i)=>lower/step+i).map(x=>x*step)
}

例如,您可以像这样使用它:

range(10,30,3) // [10, 13, 16, 19, 22, 25, 28]
range(0,0.5,0.01) // [0, 0.01, 0.02, ... , 0.48, 0.49, 0.5]
range(1,10,2) // [1, 3, 5, 7, 9]
range(-5,10,0.5) // [-5, -4.5, -4, ... , 1, 1.5, 2]
range(5,2,-0.5) // [5, 4.5, 4, 3.5, 3, 2.5, 2]

这里是一个更容易理解的版本:

const range = (lower, upper, step) => {
  end = upper / step // Upper bound
  start = lower / step // Lower bound
  n = Math.floor(end - start) + 1 // Size that includes upper bound as well
  zeros_arr = Array(n).fill(0) // Init array with n zeros
  unscaled_arr = zeros_arr.map((_, i) => (start + i)) // Setting each zero to the upper bound + the index
  range_arr = unscaled_arr.map(x => (x * step)) // Scaling every numbers with the step
  return range_arr
}

答案 5 :(得分:0)

我在 eloquent javascript 课程中解决了这个问题。根据问题陈述,我为增量选择 default parameters 并使用 while 循环来包含第二个参数。


function range(start, stop, increment=1)
{
  let range_arr = [];
  if(start < stop)
  {
    while( start <= stop)
    {
      range_arr.push(start);
      start += increment;
    }
  }
  else{
    while( start >= stop)
    {
      range_arr.push(start);
      start += increment;
    }
  }
  return range_arr;
}