r3plica
r3plica

Reputation: 13387

JavaScript Array.reduce divide

I have code in my application that multiplies numbers together using array.reduce. It looks like this:

// Private function to multiply field values together
function _multipleFields(product, fields) {

    // Calculate our total        
    var total = fields.reduce(function (total, field) {

        // Get our number from our field
        var fieldValue = helper.getPropertyValue(product, field.trim()),
            number = _extractNumber(fieldValue);

        return total * number;
    }, 1);

    // Return our total
    return total;
};

I would like to use similar logic to divide numbers. I thought I would be able to just change the operator, but total in the first iteration is equal to 1. For multiplication that is fine, but for division it isn't.

Can someone give me a hand?

Upvotes: 0

Views: 1586

Answers (3)

Alnitak
Alnitak

Reputation: 339955

If your intent is to produce e.g. ((a / b) / c) given the input array [a, b, c] then you should omit the "initial value" field because there is no "identity" value for the division operator in the way that "0" is the identity to addition and "1" is the identity for multiplication.

function divideArray(array) {
    return array.reduce(function(total, number) {
        return total / number;
    });
}

This will reduce (pun not really intended) to just returning the original value if only a single value is supplied since by definition the reduce function does not call its callback if only a single value is supplied.

With appropriate separation of concerns and simplification of functions to their smallest testable units, your entire code could reduce to:

function _getFieldNumber(product, field) {
    return _extractNumber(helper.getPropertyValue(product, field.trim()));
}

function _getFieldNumbers(product, fields) {
    return fields.map(_getFieldNumber.bind(this, product));
}

function _multipleFields(product, fields) {
    return _getFieldNumbers(product, fields).reduce(multiply, 1);
}

function _divideFields(product, fields) {
    return _getFieldNumbers(product, fields).reduce(divide);
}

function multiply(a, b) { return a * b; }
function divide(a, b)   { return a / b; }

Upvotes: 3

Rajesh
Rajesh

Reputation: 24945

As you are using similar functions for multiplication and division, you should try to make them generic.

One way is to get first field and extract number from it and use this as initialValue for .reduce. This way you can keep structure same.

function _operateFields(product, fields, operand) {
  var initial = getNumericValue(product, fields[0])
  var total = fields.slice(1).reduce(function(total, field) {
    var num = getNumericValue(product, field);
    return (operand === "/") ? total / num: total * num
  }, initial);
  return total;
};

function getNumericValue(product, field) {
  return _extractNumber(helper.getPropertyValue(product, field.trim()));
}

Upvotes: 1

r3plica
r3plica

Reputation: 13387

I managed it by doing this:

// Private function to divide field values together
function _divideFields(product, fields) {

    // Calculate our total        
    var total = fields.reduce(function (total, field) {

        // Get our number from our field
        var fieldValue = helper.getPropertyValue(product, field.trim()),
            number = _extractNumber(fieldValue);

        return total ? total / number : number;
    }, 0);

    // Return our total
    return total;
};

Upvotes: 0

Related Questions