如果存在无法识别的运算符javascript,则返回一个值

时间:2019-02-23 00:39:52

标签: javascript arrays

我有一个代码,该代码可以识别数组中的运算符,并使用来基于另一个数组进行计算。下面是代码

function interpret(...args) {
  let operators = args[1]; //get the operators array
  let values = args[2] //numbers expect the first one.
  return values.reduce((ac, val, i) => {
    //check the operator at the 'i' on which we are on while iterating through 'value'
    if (operators[i] === '+') return ac + val;
    if (operators[i] === '-') return ac - val;
    if (operators[i] === '*') return ac * val;
    if (operators[i] === '/') return ac / val;
    else return -1;
  }, args[0]) //'ac' is initially set to first value.
}

console.log(interpret(1, ["+"], [1]))
console.log(interpret(4, ["-"], [2]))
console.log(interpret(1, ["+", "*"], [1, 3]))
console.log(interpret(5, ["+", "*", "-"], [4, 1, 3]))
console.log(interpret(10, ['*', '$', '+'], [5, 3, 2])) //It fails in this case and gives 1

请协助解决此问题。谢谢

4 个答案:

答案 0 :(得分:1)

您可以设置一个标志,例如invalid,以便您的reduce函数仅在发现无效的运算符时返回-1

function interpret(...args) {
  let operators = args[1]; //get the operators array
  let invalid = false; // no invalid operators
  let values = args[2] //numbers expect the first one.
  return values.reduce((ac, val, i) => {
    //check the operator at the 'i' on which we are on while iterating through 'value'
    if (!invalid) { // if invalid is false then:
      if (operators[i] === '+') return ac + val;
      if (operators[i] === '-') return ac - val;
      if (operators[i] === '*') return ac * val;
      if (operators[i] === '/') return ac / val;
    }
    // If invalid is true or the above operators did not match, then
    invalid = true; // this will only be set to true if the above if statments didn't run
    return -1 // return -1 (this will always be executred from now on as the if(!invalid) will not run the code within it anymore

  }, args[0]) //'ac' is initially set to first value.
}

console.log(interpret(1, ["+"], [1]))
console.log(interpret(4, ["-"], [2]))
console.log(interpret(1, ["+", "*"], [1, 3]))
console.log(interpret(5, ["+", "*", "-"], [4, 1, 3]))
console.log(interpret(10, ['*', '$', '+'], [5, 3, 2])) // -1

或者,您可以使用一种新方法来实现此目的,例如递归解决方案:

const oper = {
  '+': (a, b) => a + b,
  '-': (a, b) => a - b,
  '*': (a, b) => a * b,
  '/': (a, b) => a / b
};

const interpret = (n, [fc, ...calcs], [fn, ...nums]) => {
  if(fc === undefined) return n;
  if(!(fc in oper)) return -1;
  return interpret(oper[fc](n, fn), calcs, nums)
}

console.log(interpret(1, ["+"], [1]))
console.log(interpret(4, ["-"], [2]))
console.log(interpret(1, ["+", "*"], [1, 3]))
console.log(interpret(5, ["+", "*", "-"], [4, 1, 3]))
console.log(interpret(10, ['*', '$', '+'], [5, 3, 2])) // -1

答案 1 :(得分:0)

我建议将所有可能的操作存储在operator => function的映射中,例如:

const operations = {
  "+": function(a, b) { return a + b; },
  "-": function(a, b) { return a - b; },
  "*": function(a, b) { return a * b; },
  "/": function(a, b) { return a / b; }
};

然后您可以执行该操作,如果不存在该操作,请返回NaN以将最终结果转换为NaN。最后,只需检查结果是否为NaN,然后返回-1。另外,如果您只能声明变量,我也不建议使用arguments

const operations = {
  "+": (a, b) => a + b,
  "-": (a, b) => a - b,
  "*": (a, b) => a * b,
  "/": (a, b) => a / b
};

function empty() { return NaN; }

function numberOrDefault(res, def) { return isNaN(res) ? def : res; }

function interpret(start, operators, values) {
  return numberOrDefault(values.reduce((acc, val, i) => (operations[operators[i]] || empty)(acc, val), start), -1);
}

console.log(interpret(1, ["+"], [1]));
console.log(interpret(4, ["-"], [2]));
console.log(interpret(1, ["+", "*"], [1, 3]));
console.log(interpret(5, ["+", "*", "-"], [4, 1, 3]));
console.log(interpret(10, ['*', '$', '+'], [5, 3, 2]));

如果您不想更改任何内容,请使用以下更改最少的解决方案:

function interpret(...args) {
  let operators = args[1]; //get the operators array
  let values = args[2] //numbers expect the first one.
  let result = values.reduce((ac, val, i) => {
    //check the operator at the 'i' on which we are on while iterating through 'value'
    if (operators[i] === '+') return ac + val;
    if (operators[i] === '-') return ac - val;
    if (operators[i] === '*') return ac * val;
    if (operators[i] === '/') return ac / val;
    else return NaN;
  }, args[0]); //'ac' is initially set to first value.
  return isNaN(result) ? -1 : result;
}

console.log(interpret(1, ["+"], [1]))
console.log(interpret(4, ["-"], [2]))
console.log(interpret(1, ["+", "*"], [1, 3]))
console.log(interpret(5, ["+", "*", "-"], [4, 1, 3]))
console.log(interpret(10, ['*', '$', '+'], [5, 3, 2]))

答案 2 :(得分:0)

如果要扫描操作和验证给定输入合理性的值,我实际上会在解释之前添加一个“解析”阶段 为避免任何可能的意外,我将实际解释括在try / catch中。

我也非常喜欢尼克的解决方案,所以我将从中得到一些启发。

const oper = {
  '+': (a, b) => a + b,
  '-': (a, b) => a - b,
  '*': (a, b) => a * b,
  '/': (a, b) => a / b
};
const opers = Object.keys(oper)

function interpret(...args) {
  let operators = args[1];
  let values = args[2]

  const validOperators = operators.every(op => opers.includes(op) )
  const validValues = values.every(val => typeof val === "number" )

  if(!validOperators || !validValues)
    return -1

  try {
    return values.reduce((ac, val, i) => {
        const curOper = operators[i]
        return oper[curOper](ac, val)
      }, args[0])
  } catch(e){
    return -1
  }
}

console.log(interpret(1, ["+"], [1]))
console.log(interpret(4, ["-"], [2]))
console.log(interpret(1, ["+", "*"], [1, 3]))
console.log(interpret(5, ["+", "*", "-"], [4, 1, 3]))
console.log(interpret(10, ['*', '$', '+'], [5, 3, 2]))
console.log(interpret(10, ['*', '*', '+'], [5, 3, "dog"]))

答案 3 :(得分:0)

以下演示:

  • 签名;
      

    calc(operators, numbers)

  • 第一个参数是运算符的整数数组,范围为0到3:
      

    0: + 1: - 2: * 3: /
      例如 [0、1、3、3、2] +-//*

  • 第二个参数是要计算的浮点数数组。
  • 为获得最佳操作:

    • 第二个参数的长度应比第一个参数的长度大一倍
        

      例如calc([1, 0, 3], [24, 88, 185, 11]) //11

  • 最佳输入以外的行为:

    • 如果第二个参数的长度的长度大于或等于第一个参数的长度的2倍,则第二个参数的长度将被截断,使其长度比第一个参数的长度大一个。
        

      例如calc([1, 0, 3], [24, 88, 185, 11, 325]) //11

    • 如果两个参数的长度相等或第一个参数的长度大于第二个参数的长度,则第一个参数中的多余数字将被忽略。
        

      例如calc([1, 0, 3, 2, 1], [24, 88, 185, 11]) //11

    • 如果第二个参数中只有一个数字,或者第一个参数中的数字不是[0-3],则返回该数字。这种行为就像计算器处理错误输入的方式一样。
        

      例如calc([1, 0, 3], [11]) //11

我将第一个参数设置为数字数组,因为字符串可能很乱,而且除非有意进行,否则任何输入都应该有0%的机会是非数字的。链式三元确定reduce()的每个迭代的运算符。运算符不声明initialValue,而是在第二次迭代中加入,以便处理交替模式:

// First iteration: 
numbers[0] // Accumulator
 // Second iteration:
operators[0], numbers[0] /* Accumulator */ numbers[1] // currentValue

演示

/*
@Params
|-operators: Array of numbers | range [0-3] 
| 0: +, 1: -, 2: *, 3: /
|-numbers: Array of floats
| numbers.length = operators.length + 1
@Return
|-a float
*/
const calc = ([...opr], [...num]) => {
  return num.reduce((acc, cur, idx) => {
    if (num.length - opr.length !== 1) {
      num.length = opr.length + 1
    }
    if (idx > 0) {
      let op = opr[idx - 1];
      let exp = (op === 0) ? acc + cur : (op === 1) ? acc - cur : (op === 2) ? acc * cur : (op === 3) ? acc / cur : acc + 0;
      return exp;
    }
  });
}

console.log(calc([1], [1, 5, 22]));
console.log(calc([0, 1], [55, 2, 0.3]));
console.log(calc([2, 3], [22, 6]));
console.log(calc([3, 1, 2], [51, 3, 3, 5]));
console.log(calc([1, 0, 3], [24, 88, 185, 11]));
console.log(calc([0], [94]));
console.log(calc([5, 6, 1], [94, 22]));