2

I am writing a simple reduce function:

var tiles = [
  {
    "date": "2017-11-26",
    "cloudCoverage": 92.2,
    "area": 12055600804
  },
  {
    "date": "2017-11-26",
    "cloudCoverage": 92.78,
    "area": 12055600804
  },
  {
    "date": "2017-11-26",
    "cloudCoverage": 97.29,
    "area": 11609327018
  }
]

function selectDateTile(tiles) {
  return tiles.reduce((tile, currentPick) => {
    console.log('tileArea: ', tile.area, 'currentPick area: ', currentPick.area)
    return tile.area + currentPick.area
  });
}

console.log(selectDateTile(tiles))

I would expect it to log the actual values of the objects, and the sum of all the areas:

"tileArea: " 12055600804 "currentPick area: " 12055600804 "tileArea: " 12055600804 "currentPick area: " 24111201608 ...

But the console output I am getting in jsbin is:

"tileArea: " 12055600804 "currentPick area: " 12055600804 "tileArea: " undefined "currentPick area: " 11609327018 NaN

What am I doing wrong?

jsbin reference

Miha Šušteršič
  • 9,742
  • 25
  • 92
  • 163
  • 1
    Does this answer your question? [Array reduce function is returning NAN](https://stackoverflow.com/questions/39698450/array-reduce-function-is-returning-nan) – Sebastian Simon Apr 09 '21 at 14:24
  • Or better: [How to call reduce on an array of objects to sum their properties?](https://stackoverflow.com/q/5732043/4642212). – Sebastian Simon Apr 09 '21 at 14:35

2 Answers2

8

Remember that the first argument passed to your callback is the accumulator, and your callback is supposed to return updated version of that accumulator, which is then used on the next call. So tile will only be an entry from the array on the first call; after that, it will be whatever your callback returns.

If you're looking to sum up the area properties, you want to supply an initial value for the accumulator (the second argument to reduce) and then use it as a value, not an object:

function selectDateTile(tiles) {
  return tiles.reduce((sum, currentPick) => { // <== Note `sum` parameter
    return sum + currentPick.area;            // <== Using `sum`
  }, 0);                                      // <== 0 as initial value
}

Live Example:

var tiles = [
  {
    "date": "2017-11-26",
    "cloudCoverage": 92.2,
    "area": 12055600804
  },
  {
    "date": "2017-11-26",
    "cloudCoverage": 92.78,
    "area": 12055600804
  },
  {
    "date": "2017-11-26",
    "cloudCoverage": 97.29,
    "area": 11609327018
  }
];

function selectDateTile(tiles) {
  return tiles.reduce((sum, currentPick) => { // <== Note `sum` parameter
    return sum + currentPick.area;            // <== Using `sum`
  }, 0);                                      // <== 0 as initial value
}

console.log(selectDateTile(tiles));

You could write your callback so that it detected whether it was passed an entry as the first parameter or the accumulator, but it unnecessarily complicates the code.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
1

What am I doing wrong?

You are not checking if the tile has area property or not since it is an accumulator and after first iteration it will be just a number

function selectDateTile(tiles) {
  return tiles.reduce((tile, currentPick) => {
    console.log('tileArea: ', tile.area, 'currentPick area: ', currentPick.area)
    return tile.area ? tile.area + currentPick.area : tile + currentPick.area;
  });
}
gurvinder372
  • 66,980
  • 10
  • 72
  • 94