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

2

2 Answers 2

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.

Sign up to request clarification or add additional context in comments.

Comments

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;
  });
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.