Подтвердить что ты не робот

Передача математического оператора в качестве параметра

Я хотел бы написать функцию в 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.
4b9b3361

Ответ 1

Вы не можете передать оператор в качестве параметра, но вы можете передать функцию:

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 функция 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), вы также можете использовать синтаксис " функции стрелки", чтобы сделать ваш код немного более компактным:

accumulate(list, (a, b) => a * b);

Ответ 2

Если все операции, которые вы планируете делать, это двоичные операции, вы можете сделать это

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

Ответ 3

Я думаю, вы можете сделать это несколькими разными способами, но я бы предложил вам что-то вроде этого:

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, если список пуст.

Ответ 4

Я знаю, что это старый вопрос. Просто добавив еще немного информации.

Если вы часто пользуетесь операторами и хотите 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

просто передайте 1 или -1 в качестве ввода, затем умножьте все элементы на это после wh.

Ответ 6

К сожалению, его действительно невозможно сделать так, как вы пытаетесь сделать. То, что я хотел бы сделать, это передать число и иметь if/then или switch/case, чтобы решить, что делать на основе этого числа