Program does not enumerate in JavaScript

Viewed 488

I am trying to write a program that takes an input (library, authorName) and returns the title of books the author wrote.

The library looks like this:

let library = [
  { author: 'Bill Gates', title: 'The Road Ahead', libraryID: 1254 },
  { author: 'Carolann Camilo', title: 'Eyewitness', libraryID: 32456 },
  { author: 'Carolann Camilo', title: 'Cocky Marine', libraryID: 32457 }
];

My code looks like this:

let library = [
  { author: 'Bill Gates', title: 'The Road Ahead', libraryID: 1254 },
  { author: 'Carolann Camilo', title: 'Eyewitness', libraryID: 32456 },
  { author: 'Carolann Camilo', title: 'Cocky Marine', libraryID: 32457 }
];

function searchBooks(library, author) {
  for (author in library) { //enumerate
    if (author in library) {
      let line = Object.values(library[0]) // find line of the wanted author
      let result = (line[0] + "," + line[1]) // store author name and title name
      return result
    } else {
      return "NOT FOUND"
    }
  }
}

console.log(searchBooks(library, 'Bill Gates'))

The output looks like this: Bill Gates,The Road Ahead

The problem: No matter what author I will input into searchBook it returns Bill Gates, the first line of the library. Thus, it does not enumerate I guess. But why not?

I first thought maybe I have to avoid hard coding [0] and [1] and instead use i and i++. But this does not seem to work either as it then outputs TypeError: Cannot convert undefined or null to object

4 Answers

A few things:

  1. for (author in library) is looking up each key of your library array, instead use of which evaluates each value. Since it's an object, I've named that value book
  2. your result may have many values, so best to make it an array or collection of some sort, which you can stack responses in
  3. if (author in library) checks to see if your author is a key in the original library array, again not desired. You really want to see if author is a value of the object. More specifically, you want your author to be a value of the object's author key. So book.author == author
  4. your result is an array, so join the values with a newline; if there are no items in your result array it will be an empty string, which is a falsey value. In that case that's when you can return your NOT FOUND message. Otherwise you want to return all the books

let library = [
  { author: 'Bill Gates', title: 'The Road Ahead', libraryID: 1254 },
  { author: 'Carolann Camilo', title: 'Eyewitness', libraryID: 32456 },
  { author: 'Carolann Camilo', title: 'Cocky Marine', libraryID: 32457 }
];

function searchBooks(library, author) {
  let result = []

  for (let book of library) {
    if (book.author == author) {
      let line = Object.values(book)       // find line of the wanted author
      result.push(line[0] + "," + line[1]) // store author name and title name
    }
  }

  return result.join('\n') || 'NOT FOUND'
}

console.log(1, searchBooks(library, 'Carolann Camilo'))
console.log(2, searchBooks(library, 'Bill Gates'))
console.log(3, searchBooks(library, 'Oh boy'))

Note:

  • For ways to avoid Object.values see this answer
  • For ways to iterate over the library for only desired books (using filter), seek this answer
  • For another way to iterate over library (using forEach), seek this answer

You may want to use Array.filter (see MDN):

const library = [
  { author: 'Bill Gates', title: 'The Road Ahead', libraryID: 1254 },
  { author: 'Carolann Camilo', title: 'Eyewitness', libraryID: 32456 },
  { author: 'Carolann Camilo', title: 'Cocky Marine', libraryID: 32457 }
];

console.log(findAuthor(library, `Bill Gates`));

function findAuthor(library, author) {
  return library.filter(book => book.author === author);
}

Here's a working version of your approach:

let library = [
    { author: 'Bill Gates', title: 'The Road Ahead', libraryID: 1254 },
    { author: 'Carolann Camilo', title: 'Eyewitness', libraryID: 32456 },
    { author: 'Carolann Camilo', title: 'Cocky Marine', libraryID: 32457 }
];

function searchBooks(library, author) {
    for (const book of library) { //enumerate
        if (book.author === author) {
            let result = (book.author + "," + book.title) // store author name and title name
            return result
        }
    }
    return 'NOT FOUND'
}

console.log(searchBooks(library, 'Bill Gates'))

  • First, iterate the books in the library, not the author.

  • Then find out if the author of the book is equal to the author you want to find.

  • Then output the author and title of that book separated by a comma.

Also be aware this only returns the first match, not all matches.

You can use forEach to loop over the elements and add them to a given result for multiple entries of the same author

let library = [
  {author: 'Bill Gates', title: 'The Road Ahead', libraryID: 1254 },
  { author: 'Carolann Camilo', title: 'Eyewitness', libraryID: 32456 },
  { author: 'Carolann Camilo', title: 'Cocky Marine', libraryID: 32457 }
];
function search(library, author) {
  let result = ""
  library.forEach(l => {
    if (l.author === author) {
      result += l.author+", "+l.title+"\n"
    }
  })
  return result
}

console.log(search(library, "Carolann Camilo"))
Related