Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Return undefined when using reduce

Consider the following array:

const books = [
  {
    id: 1,
    name: 'A song of ice and fire',
    genre: 'Fantasy',
    author: {
      name: 'George R. R. Martin',
      birthYear: 1948,
    },
    releaseYear: 1991,
  },
  {
    id: 2,
    name: 'The lord of the rings',
    genre: 'Fantasy',
    author: {
      name: 'J. R. R. Tolkien',
      birthYear: 1892,
    },
    releaseYear: 1954,
  },
  {
];

Suppose I want to print the book with the longest title. The following works:

const longestBook = () => {
  const longestName = books.reduce((accumulator, book) => {
      if (book.name.length > accumulator.name.length) {
        return book;
      }
      return accumulator;
    });
  return longestName
}

console.log(longestBook().name);

My question is, why can’t I return book.name / accumulator.name directly instead of using .name only when calling the function? If I try to do so, the result is undefined.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

const longestBook = () => {
  const longestName = books.reduce((accumulator, book) => {
      if (book.name.length > accumulator.name.length) {
        return book.name;
      }
      return accumulator.name;
    });
  return longestName
}

console.log(longestBook());

>Solution :

With reduce, you’re passing along a single value – the accumulator – from the previous iteration to the current iteration. In decently-structured reduce callbacks, the accumulator should usually stay the same shape throughout the loop, so that logic can be performed on it predictably and consistenly.

If you try to return the .name only, there are problems:

  const longestName = books.reduce((accumulator, book) => {
      if (book.name.length > accumulator.name.length) {
        return book.name;
      }
      return accumulator.name;
    });

because

  • Because you did not provide an initial value, the accumulator for the first iteration will be the first book object
  • Inside the first iteration, you return a .name from either the first book object or the second book object. The name is a string, so this results in the accumulator being a string for the second iteration
  • In the second iteration, the accumulator is now a string – not a book object – so return accumulator.name does not return anything.
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading