javascript 将数学运算符作为参数传递
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22303738/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Passing a math operator as a parameter
提问by Talen Kylon
I'd like to write a function in Javascript that allows me to pass in a mathematical operator and a list of ints and for each item in that list, apply the operator to it.
我想用 Javascript 编写一个函数,它允许我传入一个数学运算符和一个整数列表,并且对于该列表中的每个项目,将运算符应用于它。
Thinking of it in terms of a sum, this is what I've come up with:
从总和的角度考虑,这就是我想出的:
function accumulate(list, operator){
var sum = 0;
for each(var item in list){
sum = accumulator(sum, item);
}
print(sum);
}
Testing this code produces the following error:
测试此代码会产生以下错误:
var list = new Array();
list[0] = 1;
list[1] = 2;
list[2] = 3;
js> accumulate(list, +);
js: "<stdin>", line 9: syntax error
js: accumulate(list, +);
js: ..................^
js: "<stdin>", line 9: Compilation produced 1 syntax errors.
回答by p.s.w.g
You can't pass an operator as a parameter, but you can pass a function:
您不能将运算符作为参数传递,但可以传递函数:
function accumulate(list, accumulator){ // renamed parameter
var sum = 0;
for(var i = 0; i < list.length; i++){ // removed deprecated for…each loop
sum = accumulator(sum, list[i]);
}
print(sum);
}
accumulate(list, function(a, b) { return a + b; });
This is pretty close to what the Array.prototype.reduce
function does, though not exactly. To mimic the behavior of reduce
, you'd have to get the first element from list
and use that as the seed for your accumulator, rather than always using 0:
这与Array.prototype.reduce
函数的作用非常接近,尽管不完全相同。要模仿 的行为reduce
,您必须从中获取第一个元素list
并将其用作累加器的种子,而不是始终使用 0:
function accumulate(list, accumulator, seed){
var i = 0, len = list.length;
var acc = arguments.length > 2 ? seed : list[i++];
for(; i < len; i++){
acc = accumulator(acc, list[i]);
}
print(acc);
}
This way, you could compute the product of list
(your method would always return 0):
这样,您可以计算list
(您的方法将始终返回 0)的乘积:
accumulate(list, function(a, b) { return a * b; });
Update: If you're developing for newer browsers that support ECMAScript 2015 / ES6 (or using a transpiler like Babel), you can also use 'arrow function'syntax to make your code a bit more compact:
更新:如果您正在为支持 ECMAScript 2015 / ES6(或使用 Babel 之类的转译器)的较新浏览器开发,您还可以使用“箭头函数”语法使您的代码更加紧凑:
accumulate(list, (a, b) => a * b);
回答by thefourtheye
If all the operations you are planning to do are binary operations, then you can do this
如果你计划做的所有操作都是二元操作,那么你可以这样做
var operations = {
"+" : function (operand1, operand2) {
return operand1 + operand2;
},
"-" : function (operand1, operand2) {
return operand1 - operand2;
},
"*" : function (operand1, operand2) {
return operand1 * operand2;
}
};
function accumulate(list, operator) {
return list.reduce(operations[operator]);
}
console.log(accumulate([1, 2, 3, 4], "+")); // 10
console.log(accumulate([1, 2, 3, 4], "-")); // -8
console.log(accumulate([1, 2, 3, 4], "*")); // 24
回答by jgrocha
I think you can do that in several different ways, but I would suggest you something like this:
我认为你可以通过几种不同的方式做到这一点,但我建议你这样做:
var operatorFunction = {
'+' : function(x, y) {
return x + y;
},
'-' : function(x, y) {
return x - y;
},
'*' : function(x, y) {
return x * y;
}
};
function accumul(list, neutral, operator) {
var sum = neutral;
list.forEach(function(item) {
sum = operatorFunction[operator](sum, item);
});
return sum;
}
console.log(accumul([2, 3, 4], 0, '+'));
console.log(accumul([2, 3, 4], 0, '-'));
console.log(accumul([2, 3, 4], 1, '*'));
console.log(accumul([], 0, '+'));
console.log(accumul([], 1, '*'));
In the example above, you just need something like accumul([2, 3, 4], 0, '+');
to call you function. operatorFunction[operator]
calls the correspondent operator function.
在上面的例子中,你只需要像accumul([2, 3, 4], 0, '+');
调用函数这样的东西。operatorFunction[operator]
调用对应的运算符函数。
Running the example in the command line, with node.js, gives:
在命令行中使用node.js运行示例,给出:
$ node accumulate.js
9
-9
24
0
1
This version also work if the array is empty. You can not use list.reduce
if the list is empty.
如果数组为空,此版本也适用。list.reduce
如果列表为空,则不能使用。
回答by rellampec
I know this is an old question. Just adding some more information.
我知道这是一个老问题。只是添加更多信息。
If you often use operators and need to reduce
the results (accumulate
), it is highly recommended to develop different helpers, so you can quickly use any input form to obtain the results.
如果你经常使用操作符并且需要reduce
得到结果(accumulate
),强烈建议开发不同的帮助器,这样你就可以快速使用任何输入表单来获取结果。
Although, this will not be always the case when you use reduce
, the following helper will allow to pass the first element of your array as default
value:
尽管使用 时情况并非总是如此reduce
,但以下帮助程序将允许将数组的第一个元素作为default
值传递:
reducer = (list, func) => list.slice(1).reduce(func, list.slice(0, 1).pop())
The above, still has a function
dependency, so you still need to declare the specific function that wraps your target operator
:
上面的,仍然有一个function
依赖,所以你仍然需要声明包装你的目标的特定函数operator
:
sum = list => reducer(list, (a, b) => a + b)
sum([1, 2, 3, 4, 5])
You could then redefine sum
, for example, as per new input formats you see will be backwards compatible. In this example by using a new helper, flat
(still experimental as per now; added the code):
然后sum
,您可以重新定义,例如,根据您看到的新输入格式将向后兼容。在这个例子中,通过使用一个新的助手,flat
(现在仍然是实验性的;添加了代码):
flat = (e) => Array.isArray(e) ? [].concat.apply([], e.map(flat)) : e
sum = (...list) => reducer(flat(list), (a, b) => a + b)
mult = (...list) => reducer(flat(list), (a, b) => a * b)
sum([1, 2, 3, 4, 5])
sum(1, 2, 3, 4, 5)
mult([1, 2, 3, 4, 5])
mult(1, 2, 3, 4, 5)
Then you can use reducer
(or any variant you may find more useful) to simplify the definition of other helpers as well. Just one last example with matrix custom operators (in this case, they are functions
):
然后您可以使用reducer
(或您可能发现更有用的任何变体)来简化其他助手的定义。矩阵自定义运算符的最后一个示例(在这种情况下,它们是functions
):
zip = (...lists) => lists[0].map((_l, i) => lists.map(list => list[i]))
dot_product = (a, b) => sum(zip(a, b).map(x => mult(x)))
mx_transpose = (mx) => zip.apply([], mx)
// the operator
mx_product = (m1, m2) =>
m1.map(row => mx_transpose(m2).map(
col => dot_product(row, col) ))
// the reducer
mx_multiply = (...mxs) => reducer(mxs, (done, mx) => mx_product(done, mx))
A = [[2, 3, 4],
[1, 0, 0]]
B = [[0, 1000],
[1, 100],
[0, 10]]
C = [[2, 0],
[0, 0.1]]
JSON.stringify(AB = mx_product (A, B))
JSON.stringify(ABC = mx_product (AB, C))
JSON.stringify(ABC2 = mx_multiply(A, B, C))
回答by Jan Kleine Deters
just pass 1 or -1 as input then multiply all items with this after wh.
只需传递 1 或 -1 作为输入,然后在 wh 之后将所有项目与此相乘。
回答by Snappawapa
Unfortunately, its not really possible to do this like you are trying to do. What I would do is pass in a number, and have a if/then or a switch/case to decide what to do based on that number
不幸的是,它不可能像您尝试做的那样做到这一点。我会做的是传入一个数字,然后使用 if/then 或 switch/case 来根据该数字决定要做什么