0

I am trying to GET total order prices (in USD) in an object array and sum the total. Instead of summing the array, the order totals are concatenated. How do I force addition instead of concatenation?

<body>
<p id=sales></p>
<script>
var sales, i, x = "";

sales = {"orders": [{"total_price_usd": "92.05"}, {"total_price_usd": "14.90"}, {"total_price_usd": "17.90"}, {"total_price_usd": "14.90"}]}

for (i in sales.orders) {
    x += sales.orders[i].total_price_usd + ', ';
}
var numbers = [x];
function getSum(total, num) {
    return parseFloat(total) + parseFloat(num);
}
document.getElementById('sales').innerHTML = '$' + numbers.reduce(getSum);
</script>
</body>
Clay T.
  • 5
  • 3
  • 4
    That's not [JSON](https://json.org). _"JSON is a textual, language-indepedent data-exchange format, much like XML, CSV or YAML."_ - [What is the difference between JSON and Object Literal Notation?](https://stackoverflow.com/questions/2904131/what-is-the-difference-between-json-and-object-literal-notation) – Andreas Feb 16 '18 at 16:37
  • 1
    `numbers` just contains a long, comma-separated string, how do you expect to be able to parse it as a number? – Federico klez Culloca Feb 16 '18 at 16:39
  • 1. The value of `total_price_usd` is a string. 2. If you want to sum numbers why do you then add `', '`? – Andreas Feb 16 '18 at 16:39
  • The server returns the total prices as strings. – Clay T. Feb 17 '18 at 15:43

4 Answers4

1

This line doesn't create an array of numbers:

var numbers = [x];

It's just creating an array with one element, a string, as if you'd written:

var numbers = ["92.05, 14.90, 17.90, 14.90"]

Then when you call numbers.reduce(), it just processes the first number in the string, it doesn't loop over them. Using a variable that contains a string doesn't cause it to parsed as if it were Javascript source.

You should do:

var numbers = []
for (var i = 0; i < sales.order.length; i++) {
    numbers.push(parseFloat(sales.order[i].total_price_usd));
}

Or you can just do the addition in this loop, instead of using reduce() later:

var total = 0;
for (var i = 0; i < sales.order.length; i++) {
    total += parseFloat(sales.order[i].total_price_usd);
}
Barmar
  • 741,623
  • 53
  • 500
  • 612
0

Using parseFloat() on the variables and initialising x to 0 should help

var sales, i, x = 0;

sales = {"orders": [{"total_price_usd": "92.05"}, {"total_price_usd": "14.90"}, {"total_price_usd": "17.90"}, {"total_price_usd": "14.90"}]}

for (i in sales.orders) {
    x += parseFloat(sales.orders[i].total_price_usd);
}
var numbers = [x];
function getSum(total, num) {
    return parseFloat(total) + parseFloat(num);
}
document.getElementById('sales').innerHTML = '$' + numbers.reduce(getSum);
<div id="sales"></div>

Do note that adding floating point numbers in Javascript can lead to some pretty common discrepancies. Is floating point math broken?

Agney
  • 18,522
  • 7
  • 57
  • 75
0

Just use reduce and the Number constructor:

sales = {"orders": [{"total_price_usd": "92.05"}, {"total_price_usd": "14.90"}, {"total_price_usd": "17.90"}, {"total_price_usd": "14.90"}]}

const total = sales.orders.reduce(
  (total, order) => total + Number(order.total_price_usd), 
  0
)

console.log(total)

parseFloat and the unary + will also work, as others point out. I think Number is the most readable, but your mileage may vary.

Scott Sauyet
  • 49,207
  • 4
  • 49
  • 103
  • 1
    How does this solve the real problem? It just seems like a style change, but the bug still exists. – Barmar Feb 16 '18 at 16:43
  • What real problem do you see? I start with the initial data and return the expected total. I suppose I don't explain what's wrong with the original, but it seemed like the question was about getting addition instead of concatenation. I'll add a snippet. – Scott Sauyet Feb 16 '18 at 16:48
  • Oh, didn't see that you changed the variable you're looping over, I thought you just changed `parseFloat` to `Number`. – Barmar Feb 16 '18 at 16:49
  • Oh, that makes sense. Yes, that wouldn't do much. ;-) – Scott Sauyet Feb 16 '18 at 16:53
0
  • You can access directly to array sales.orders
  • Within function getSum get the price in USD num.total_price_usd

var sales = {"orders": [{"total_price_usd": "92.05"}, {"total_price_usd": "14.90"}, {"total_price_usd": "17.90"}, {"total_price_usd": "14.90"}]};


//------------- You need to verify this logic
var i, x = ""

// You're creating an array as follow: ["1, 2, 4, 5"].
for (i in sales.orders) {
    x += sales.orders[i].total_price_usd + ', ';
}
var numbers = [x];
//-------------------------------------------

function getSum(total, num) {
    return parseFloat(total) + parseFloat(num.total_price_usd);
}

document.getElementById('sales').innerHTML = '$' + sales.orders.reduce(getSum, 0);
<p id=sales></p>
Ele
  • 33,468
  • 7
  • 37
  • 75