我想在Javascript中编写一个函数,允许我传入一个数学运算符和一个整数列表,并为该列表中的每个项目应用运算符。
从总和来看,这就是我提出的:
function accumulate(list, operator){
var sum = 0;
for each(var item in list){
sum = accumulator(sum, item);
}
print(sum);
}
测试此代码会产生以下错误:
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.
答案 0 :(得分:28)
您不能将运算符作为参数传递,但可以传递函数:
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; });
这与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);
}
这样,您可以计算list
的乘积(您的方法将始终返回0):
accumulate(list, function(a, b) { return a * b; });
更新:如果您正在开发支持ECMAScript 2015 / ES6的新浏览器(或使用像Babel这样的转发器),您还可以使用'arrow function'语法来编写代码更紧凑:
accumulate(list, (a, b) => a * b);
答案 1 :(得分:23)
如果您计划执行的所有操作都是二进制操作,那么您可以执行此操作
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
答案 2 :(得分:4)
我认为你可以用几种不同的方式做到这一点,但我会建议你这样的事情:
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, '*'));
在上面的示例中,您只需要accumul([2, 3, 4], 0, '+');
之类的内容来调用您的功能。 operatorFunction[operator]
调用相应的运算符函数。
在命令行中使用node.js运行示例,提供:
$ node accumulate.js
9
-9
24
0
1
如果数组为空,此版本也可以使用。如果列表为空,则无法使用list.reduce
。
答案 3 :(得分:2)
var list = { a: 3, b: 7, c: 5 }
var expression = (a) => a * 2;
function computeObject(list, bc){
for(var x in list){
list[x] = bc(list[x]);
console.log(list[x]);
}
}
computeObject(list, expression);
答案 4 :(得分:0)
我知道这是一个老问题。只需添加一些更多信息即可。
如果您经常使用运算符并且需要reduce
结果(accumulate
),则强烈建议开发不同的帮助程序,以便您可以快速使用任何输入形式来获取结果。
尽管使用reduce
并非总是如此,但以下帮助程序将允许将数组的第一个元素作为default
值传递:
reducer = (list, func) => list.slice(1).reduce(func, list.slice(0, 1).pop())
以上内容仍然具有function
依赖性,因此您仍然需要声明用于包装目标operator
的特定函数:
sum = list => reducer(list, (a, b) => a + b)
sum([1, 2, 3, 4, 5])
例如,然后您可以重新定义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)
然后,您也可以使用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))
答案 5 :(得分:0)
只需传递1或-1作为输入,然后在wh之后将所有项目与此相乘。
答案 6 :(得分:0)
使用柯里化可以做得相当不错:
const calculate = a => str => b => {switch(str) {
case '+': return a + b
case '-': return a - b
case '/': return a / b
case '*': return a * b
default: return 'Invalid operation'
}}
const res = calculate(15)('*')(28)
console.log('15 * 28 =', res)
答案 7 :(得分:-4)
不幸的是,它不可能像你想要的那样做到这一点。我要做的是传入一个数字,并有一个if / then或switch / case来决定根据这个数字做什么