Javascript 如何使用两个单独的数组(一个包含值,另一个包含操作数)执行操作

Javascript 如何使用两个单独的数组(一个包含值,另一个包含操作数)执行操作,javascript,Javascript,我怎样做一个循环,这样,我就可以做下面的操作了 var num = [12, 13, 15, 22]; var oper = ["+", "-", "*"]; 我试着像下面这样做: 12 + 13 - 15 * 22 但这对我来说并不管用 我如何才能实现我期待的目标 此处不需要p.s.操作数优先级。假设num和oper格式良好,可以尝试以下操作: for(var t = 0; t < num.length - 1; t++) { retVal += num[t] oper[t]

我怎样做一个循环,这样,我就可以做下面的操作了

var num = [12, 13, 15, 22];

var oper = ["+", "-", "*"];
我试着像下面这样做:

12 + 13 - 15 * 22
但这对我来说并不管用

我如何才能实现我期待的目标

此处不需要p.s.操作数优先级。

假设num和oper格式良好,可以尝试以下操作:

for(var t = 0; t < num.length - 1; t++) {
  retVal += num[t] oper[t] num[t+1]
}
假设num和oper格式良好,可以尝试以下方法:

for(var t = 0; t < num.length - 1; t++) {
  retVal += num[t] oper[t] num[t+1]
}
如果要将其作为考虑运算符优先级的表达式进行计算,可以使用reduce和eval

var num=[12,13,15,22]; var oper=[+,-,*]; 让final=num.reduceop,inp,index=>{ op+=index==0?inp:`${oper[index-1]}${inp}` 返回操作 }, console.logevalfinal如果要将其作为考虑运算符优先级的表达式进行计算,可以使用reduce和eval

var num=[12,13,15,22]; var oper=[+,-,*]; 让final=num.reduceop,inp,index=>{ op+=index==0?inp:`${oper[index-1]}${inp}` 返回操作 },
console.logevalfinal您可以使用分隔符数组和eval表达式来连接数组。这尊重运算符的优先级

常数 join=[a,b,…数组],[s,…分隔符]=>array.length ? 联接[a+s+b,…数组],分隔符 :a+s+b; var num=[12,13,15,22], 运算符=[+,-,*], term=joinnum,oper; console.logterm;
console.logevalterm 您可以使用分隔符数组和表达式的eval连接该数组。这尊重运算符的优先级

常数 join=[a,b,…数组],[s,…分隔符]=>array.length ? 联接[a+s+b,…数组],分隔符 :a+s+b; var num=[12,13,15,22], 运算符=[+,-,*], term=joinnum,oper; console.logterm; console.logevalterm 您可以在每次迭代中使用for..of循环和链式三元循环,无需评估:

确保数字数组长度正好比运算符数组多一个元素。 .拼接数字数组的前两个数字-生成术语数组。 如果运算符为+-将术语[0]添加到术语[1] 否则,如果运算符为-,则从项[1]中减去项[0] else如果运算符为*-将项[0]乘以项[1] else if运算符为/-将项[0]除以项[1] 埃尔斯-南 将结果取消移位到数字数组的索引0。 在最后一次迭代之后,返回数字数组中第一个也是唯一一个作为实数传递的数字,否则将返回错误消息。 让数字=[12,13,15,22]; 让运算符=[+,-,*]; 函数数、运算符{ 运算符.length=number.length-1; 算子的let算子{ 设项=number.0,2; 让当前=运算符=='+'?术语[0]+术语[1]: 运算符=='-'?术语[0]-术语[1]: 运算符=='*'?术语[0]*术语[1]: 运算符=='/'?术语[0]/术语[1]:NaN; 数字。无移位电流; } return!isnanParseFloatNumber[0]&&isFiniteNumber[0]?数字[0]:“检查参数”; } console.LogCalArraysNumber、运算符 您可以在每次迭代中使用for..of循环和链式三元循环,无需评估:

确保数字数组长度正好比运算符数组多一个元素。 .拼接数字数组的前两个数字-生成术语数组。 如果运算符为+-将术语[0]添加到术语[1] 否则,如果运算符为-,则从项[1]中减去项[0] else如果运算符为*-将项[0]乘以项[1] else if运算符为/-将项[0]除以项[1] 埃尔斯-南 将结果取消移位到数字数组的索引0。 在最后一次迭代之后,返回数字数组中第一个也是唯一一个作为实数传递的数字,否则将返回错误消息。 让数字=[12,13,15,22]; 让运算符=[+,-,*]; 函数数、运算符{ 运算符.length=number.length-1; 算子的let算子{ 设项=number.0,2; 让当前=运算符=='+'?术语[0]+术语[1]: 运算符=='-'?术语[0]-术语[1]: 运算符=='*'?术语[0]*术语[1]: 运算符=='/'?术语[0]/术语[1]:NaN; 数字。无移位电流; } return!isnanParseFloatNumber[0]&&isFiniteNumber[0]?数字[0]:“检查参数”; }
console.LogCalArraysNumber、运算符 oper数组将运算符存储为字符串。在循环的第一次迭代中,行retVal+=num[t]oper[t]num[t+1正在执行以下赋值:

var num = [
  12, 13, 15, 22
];
var oper = [
  "+", "-", "*"
];

var exp = '';
while (num.length || oper.length) {
  if (num.length) {
    exp += num.shift();
  }
  if (oper.length) {
    exp += oper.shift();
  }
}

var result = eval(exp);
console.log(result);
12+13不是有效的语法,它只是两个数字和一个并排的字符串。这没用

此外,在for循环的最后一次迭代中,您将引用num数组的一个不存在的索引。t是3,num[3+1],即num[4]不存在。您需要修复for逻辑,以便保持在数组的范围内

有几种方法可以解决这个问题 继续执行oper数组中指定的操作。例如,您可以将数组元素连接成一个字符串,然后使用eval函数计算该字符串。假设num和oper被保证正确格式化,那么一个简单的实现可能如下所示:

retVal += 12 "+" 13
与eval技术不同,它返回220。这是因为操作完全按照oper数组的顺序执行,而不是按照数学顺序执行

在决定实现什么方法时,应该考虑这种操作顺序


为了再次迭代,我的示例中的for循环只是为了演示这个特定的示例,在其他条件下很可能会失败。围绕实际使用中可能需要的num和oper值构建逻辑。

oper数组将运算符存储为字符串。在循环的第一次迭代中,行retVal+=num[t]oper[t]num[t+1正在执行以下赋值:

var num = [
  12, 13, 15, 22
];
var oper = [
  "+", "-", "*"
];

var exp = '';
while (num.length || oper.length) {
  if (num.length) {
    exp += num.shift();
  }
  if (oper.length) {
    exp += oper.shift();
  }
}

var result = eval(exp);
console.log(result);
12+13不是有效的语法,它只是两个数字和一个并排的字符串。这没用

此外,在for循环的最后一次迭代中,您将引用num数组的一个不存在的索引。t是3,num[3+1],即num[4]不存在。您需要修复for逻辑,以便保持在数组的范围内

有几种方法可以执行oper数组中指定的操作。例如,您可以将数组元素连接成一个字符串,然后使用eval函数计算该字符串。假设num和oper被保证正确格式化,那么一个简单的实现可能如下所示:

retVal += 12 "+" 13
与eval技术不同,它返回220。这是因为操作完全按照oper数组的顺序执行,而不是按照数学顺序执行

在决定实现什么方法时,应该考虑这种操作顺序


为了再次迭代,我的示例中的for循环只是为了演示这个特定的示例,在其他条件下很可能会失败。围绕实际使用中可能期望的num和oper值构建逻辑。

我将定义对应于oper中每个可能值的二进制函数,然后使用reduce获得从左到右的累加:

常数func={ +:a,b=>a+b, -:a,b=>a-b, *:a,b=>a*b, /:a,b=>a/b }; const leftToRight=nums,opers=>nums.reducea,b,i=>func[opers[i-1]]a,b;
控制台.logleftorRight[12,13,15,22],+,-,*] 我将定义对应于oper中每个可能值的二进制函数,然后使用reduce获得从左到右的累加:

常数func={ +:a,b=>a+b, -:a,b=>a-b, *:a,b=>a*b, /:a,b=>a/b }; const leftToRight=nums,opers=>nums.reducea,b,i=>func[opers[i-1]]a,b;
控制台.logleftorRight[12,13,15,22],+,-,*] 我将添加一个具有实际操作的对象:

var num = [ 12, 13, 15, 22 ];
var oper = [ "+", "-", "*" ];
var result = num[0]
for (var i = 0; i < oper.length; i++ ) {
    switch(oper[i]) {
      case '+' : result += num[i+1]; break;
      case '-' : result -= num[i+1]; break;
      case '*' : result *= num[i+1]; break;
    }
}
return eval(result);
然后使用reduce:

var num=[ 12, 13, 15, 22 ]; 变量操作=[ +, -, * ]; var opFunc={ “+”:a,b=>Numbera+Numberb, “-”:a,b=>Numbera-Numberb, “*”:a,b=>Numbera*Numberb, “/”:a,b=>Numbera/Numberb } var res=num.reduceac,x,i=> opFunc[oper[i-1]]ac,x
console.logres我将添加一个具有实际操作的对象:

var num = [ 12, 13, 15, 22 ];
var oper = [ "+", "-", "*" ];
var result = num[0]
for (var i = 0; i < oper.length; i++ ) {
    switch(oper[i]) {
      case '+' : result += num[i+1]; break;
      case '-' : result -= num[i+1]; break;
      case '*' : result *= num[i+1]; break;
    }
}
return eval(result);
然后使用reduce:

var num=[ 12, 13, 15, 22 ]; 变量操作=[ +, -, * ]; var opFunc={ “+”:a,b=>Numbera+Numberb, “-”:a,b=>Numbera-Numberb, “*”:a,b=>Numbera*Numberb, “/”:a,b=>Numbera/Numberb } var res=num.reduceac,x,i=> opFunc[oper[i-1]]ac,x
logres已经介绍了很多有用的方法。我认为缺少的是将数据组合到堆栈中,然后像基于堆栈的处理器一样处理它

在这里,makeStack只是将您的值散布到一个数组中,evalStack将运算符名称映射到二进制函数和散布的数组中,返回一个值,而process只是将这些操作组合到一个函数中

const makeStack=num,oper=> [num[0],…num.slice 1.flatMap n,i=>[n,oper[i]] const evalStack=ops,[a,b=undefined,op=undefined,…xs]=> b==未定义 ? A. :evalStackops[ops[ops]a,b,…xs] 常量进程=ops,num,oper=> evalStack操作,makeStack数量,操作 警察行动={ “+”:a,b=>a+b, “-”:a,b=>a-b, “*”:a,b=>a*b, “/”:a,b=>a/b, //…你想要的任何其他运营商 } const num=[12,13,15,22] 常量运算符=[+,-,*] 控制台日志 进程操作,num,oper
已经提出了许多有用的方法。我认为缺少的是将数据组合到堆栈中,然后像基于堆栈的处理器一样处理它

在这里,makeStack只是将您的值散布到单个数组中,ev alStack将运算符名称映射到二进制函数和散布的数组,并返回一个值,然后进程将这些操作简单地组合到单个函数中

const makeStack=num,oper=> [num[0],…num.slice 1.flatMap n,i=>[n,oper[i]] const evalStack=ops,[a,b=undefined,op=undefined,…xs]=> b==未定义 ? A. :evalStackops[ops[ops]a,b,…xs] 常量进程=ops,num,oper=> evalStack操作,makeStack数量,操作 警察行动={ “+”:a,b=>a+b, “-”:a,b=>a-b, “*”:a,b=>a*b, “/”:a,b=>a/b, //…你想要的任何其他运营商 } const num=[12,13,15,22] 常量运算符=[+,-,*] 控制台日志 进程操作,num,oper

试试这个:eval'retVal+=num[t]'+oper[t]+'num[t+1]';使用该参数将超出数组长度for@charlietfl怎样我从0开始小于数组的长度,但在最后一次迭代中。。。num[t+1]是undefined@charlietfl没错,你是对的。我不知道为什么我使用了我的旧代码,但我更新了以使其正确。请尝试以下操作:eval'retVal+=num[t]'+oper[t]+'num[t+1];使用该参数将超出数组长度for@charlietfl怎样我从0开始小于数组的长度,但在最后一次迭代中。。。num[t+1]是undefined@charlietfl没错,你是对的。我不知道为什么我用我的旧代码,但我更新了使其正确。有些不正确。。。仅15x22就不仅仅是最终版本result@charlietfl我从左到右计算,一次两个oprand,因此计算为12+13-15*22@charlietfl抱歉,让我澄清一下。首先感谢您的回复。操作数顺序与我的情况无关。它是按它出现的顺序排列的。所以a+可以在*之前,如果它先出现的话。上述问题的答案应该是220@Si8如果你想一次计算两个值,而不考虑运算符优先级,那么我的原始答案就足够了,如果你想作为表达式计算,也考虑运算符优先级,你需要使用更新后的表达式。。。仅15x22就不仅仅是最终版本result@charlietfl我从左到右计算,一次两个oprand,因此计算为12+13-15*22@charlietfl抱歉,让我澄清一下。首先感谢您的回复。操作数顺序与我的情况无关。它是按它出现的顺序排列的。所以a+可以在*之前,如果它先出现的话。上述问题的答案应该是220@Si8如果你想一次计算两个值而不考虑运算符优先级,那么我的原始答案就足够了,如果你想作为表达式计算而考虑运算符优先级,你需要使用更新的表达式谢谢,但运算符优先级并不重要,这是它出现的顺序。请在问题@Si8中明确说明这一点。后一个答案非常优雅。。。或者扭曲,我不确定是哪一个我从来没有利用过reduce的非初始化版本,我认为这是一个很好的理由,也没有使用过Array.prototype.values。但它们一起构成了一个非常好的解决方案。谢谢,但运算符优先级并不重要,它是按照它出现的顺序。请在问题@Si8中明确说明这一点。后一个答案非常优雅。。。或者扭曲,我不确定是哪一个我从来没有利用过reduce的非初始化版本,我认为这是一个很好的理由,也没有使用过Array.prototype.values。但是他们一起做了一个非常好的解决方案。谢谢伊恩的回答谢谢伊恩的回答谢谢你的回答!从未听说过福斯,但很高兴知道:。我想知道还有哪些编程语言是我还没有听说过的。我将测试您的代码并让您知道它是如何运行的。再次感谢@Scotthanks的回答!从未听说过福斯,但很高兴知道:。我想知道还有哪些编程语言是我还没有听说过的。我将测试您的代码并让您知道它是如何运行的。再次感谢@Scott