#JavaScript April 03, 2023

Notes on JS Array of Objects

The following are my notes on array of objects. An array of object is a collection of several objects. Each book in the example below is an object, where the syntax is called object literal. An object literal is a syntax for creating a single object in JavaScript by specifying its properties and values using curly braces {}.
Each detail about the book is a key-value pair. Where title, author, and genre are each called a property and their respective data is called value.
const books = [{
  title: "To Kill a Mockingbird",
  author: "Harper Lee",
  publishedYear: 1960,
  genre: ["Fiction", "Historical Fiction"],
  pageCount: 281,
  price: 12.99,
  inStock: 5,
  isHardcover: false,
  rating: 4.5,
  reviews: [
    {
      username: "booklover123",
      rating: 5,
      text: "This is one of the best books I've ever read!",
      date: "2022-01-05"
    },
    {
      username: "avidreader456",
      rating: 4,
      text: "A classic that is definitely worth reading.",
      date: "2022-02-10"
    }
  ]
},
{
  title: "The Great Gatsby",
  author: "F. Scott Fitzgerald",
  publishedYear: 1925,
  genre: ["Fiction", "Historical Fiction"],
  pageCount: 180,
  price: 9.99,
  inStock: 2,
  isHardcover: true,
  rating: 4.2,
  reviews: [
    {
      username: "gatsbyfan",
      rating: 5,
      text: "This book is a literary masterpiece!",
      date: "2022-03-20"
    },
    {
      username: "bookworm123",
      rating: 3,
      text: "I enjoyed this book, but it's not my favorite.",
      date: "2022-02-15"
    }
  ]
},
{
  title: "The Hunger Games",
  author: "Suzanne Collins",
  publishedYear: 2008,
  genre: ["Fiction", "Science Fiction"],
  pageCount: 374,
  price: 14.99,
  inStock: 8,
  isHardcover: false,
  rating: 4.7,
  reviews: [
    {
      username: "hungergamesfan",
      rating: 5,
      text: "This book is a thrilling ride from start to finish!",
      date: "2022-03-28"
    },
    {
      username: "scifibooklover",
      rating: 4,
      text: "I'm not usually a fan of YA fiction, but this book surprised me.",
      date: "2022-01-30"
    }
  ]
}
];

Now, here's a guide on how to extract any information from an array of objects.

1. Getting the author of the book "To Kill a Mockingbird".

Using a regular function and the find() method: const author = books.find(function(book) {
  return book.title === "To Kill a Mockingbird";
}).author;
console.log(author); // "Harper Lee"

Using the arrow function: const author = books.find(book => book.title === "To Kill a Mockingbird").author;
console.log(author); // "Harper Lee"

Using the filter() method: const book = books.filter(book => book.title === "To Kill a Mockingbird");
const author = book.length > 0 ? book[0].author : undefined;
console.log(author); // "Harper Lee"

Using a for loop: let author;
for (let i = 0; i < books.length; i++) {
  if (books[i].title === "To Kill a Mockingbird") {
    author = books[i].author;
    break;
  }
}
console.log(author); // "Harper Lee"

2. Getting the genres of the book "To Kill a Mockingbird".

To get the first genre of the array of genre:
const genre = books.find(book => book.title === "To Kill a Mockingbird").genre[0];
console.log(genre); // "Fiction"

To get the last genre:
const genres = books.find(book => book.title === "To Kill a Mockingbird").genre;
const lastGenre = genres[genres.length - 1];
console.log(lastGenre); // "Historical Fiction"

To get the all genre:
const genres = books.find(book => book.title === "To Kill a Mockingbird").genre;
console.log(genres); // ["Fiction", "Historical Fiction"]

3. Getting the reviews of the book "To Kill a Mockingbird".

To get the first review of the object "review":
const firstReview = books.find(book => book.title === "To Kill a Mockingbird").reviews[0];
console.log(firstReview); // { username: "booklover123", rating: 5, text: "This is one of the best books I've ever read!", date: "2022-01-05" }

To get the last review:
const reviews = books.find(book => book.title === "To Kill a Mockingbird").reviews;
const lastReview = reviews[reviews.length - 1];
console.log(lastReview); // { username: "avidreader456", rating: 4, text: "A classic that is definitely worth reading.", date: "2022-02-10" }

To get all the reviews:
const reviews = books.find(book => book.title === "To Kill a Mockingbird").reviews;
console.log(reviews); // [{ username: "booklover123", rating: 5, text: "This is one of the best books I've ever read!", date: "2022-01-05" }, { username: "avidreader456", rating: 4, text: "A classic that is definitely worth reading.", date: "2022-02-10" }]

4. Getting all details of the book "To Kill a Mockingbird".

const bookDetails = books.find(book => book.title === "To Kill a Mockingbird");
console.log(bookDetails);

5. Getting all the titles in the object array.

Using the map() method const titles = books.map(book => book.title);
console.log(titles); // ["To Kill a Mockingbird", "The Great Gatsby", "The Hunger Games"]

Using a for loop: const titles = [];
for (let i = 0; i < books.length; i++) {
  titles.push(books[i].title);
}
console.log(titles); // ["To Kill a Mockingbird", "The Great Gatsby", "The Hunger Games"]

Using for...of loop: const titles = [];
for (const book of books) {
  titles.push(book.title);
}
console.log(titles); // ["To Kill a Mockingbird", "The Great Gatsby", "The Hunger Games"]

Using the forEach() method: const titles = [];
books.forEach(book => titles.push(book.title));
console.log(titles); // ["To Kill a Mockingbird", "The Great Gatsby", "The Hunger Games"]

Using the reduce() method: const titles = books.reduce((result, book) => {
  result.push(book.title);
  return result;
}, []);
console.log(titles); // ["To Kill a Mockingbird", "The Great Gatsby", "The Hunger Games"]

Without declaring the titles variable:

Using map(): console.log(books.map(book => book.title)); // ["To Kill a Mockingbird", "The Great Gatsby", "The Hunger Games"]

Using a for loop: for (let i = 0; i < books.length; i++) {
  console.log(books[i].title);
} // "To Kill a Mockingbird", "The Great Gatsby", "The Hunger Games"

Using for...of loop: for (const book of books) {
  console.log(book.title); // "To Kill a Mockingbird", "The Great Gatsby", "The Hunger Games"
}

Using forEach(): books.forEach(book => console.log(book.title)); // "To Kill a Mockingbird", "The Great Gatsby", "The Hunger Games"

Using reduce(): console.log(books.reduce((acc, book) => {
  acc.push(book.title);
  return acc;
}, [])); // ["To Kill a Mockingbird", "The Great Gatsby", "The Hunger Games"]

6. Getting all the unique genres.

use the reduce() method to accumulate the unique genres into a new array const uniqueGenres = books.reduce((acc, book) => {
  book.genre.forEach(genre => {
    if (!acc.includes(genre)) {
      acc.push(genre);
    }
  });
  return acc;
}, []);
console.log(uniqueGenres); // ["Fiction", "Historical Fiction", "Dystopian"]

Using Set and flatMap(): const uniqueGenres = [...new Set(books.flatMap(book => book.genre))];
console.log(uniqueGenres); // ["Fiction", "Historical Fiction", "Dystopian"]

Here, the flatMap() method is used to create a new array that contains all the genres from all the books in the books array. The resulting array may contain duplicate genres.
Then, the Set constructor is used to create a new set from the resulting array, which removes any duplicates. The spread operator (...) is used to convert the set back into an array, which is stored in the uniqueGenres variable.
Using a for...of loop and a Set: const uniqueGenres = new Set();
for (const book of books) {
  book.genre.forEach(genre => uniqueGenres.add(genre));
}
console.log([...uniqueGenres]); // ["Fiction", "Historical Fiction", "Dystopian"]

Here, a for...of loop is used to iterate over each object in the books array. Inside the loop, the forEach() method is used to iterate over each genre in the genre array property of the current book object. The add() method is used to add each unique genre to a new Set object called uniqueGenres.
Finally, the spread operator (...) is used to convert the uniqueGenres set back into an array, which is logged to the console.
Using reduce() and a Set: const uniqueGenres = books.reduce((set, book) => {
  book.genre.forEach(genre => set.add(genre));
  return set;
}, new Set());
console.log([...uniqueGenres]); // ["Fiction", "Historical Fiction", "Dystopian"]

7. Getting all the books published in year 2000.

Using the forEach method: books.forEach(book => {
  if (book.publishedYear === 2000) {
    console.log(book);
  }
});

Using filter() and forEach():
books.filter(book => book.publishedYear === 2000).forEach(book => {
  console.log(book);
});

8. Getting all the books published between 1900–2000.

console.log(books.filter(book => book.publishedYear >= 1900 && book.publishedYear <= 2000));

9. Getting the total number of book pages.

let totalPages = 0;
for (const book of books) {
  totalPages += book.pageCount;
}
console.log(totalPages);

10. Getting the average ratings of all books.

let totalRatings = 0;
books.forEach(book => {
  totalRatings += book.averageRating;
});
const averageRating = totalRatings / books.length;
console.log(averageRating);

11. Getting all the books of a specific author.

const booksByAuthor = [];
books.forEach(book => {
  if (book.author === "Harper Lee") {
    booksByAuthor.push(book);
  }
});
console.log(booksByAuthor);

12. Getting the top-rated book.

Using a forEach() loop: let topRatedBook = books[0]; // Start with the first book as the top-rated book
books.forEach(book => {
  if (book.averageRating > topRatedBook.averageRating) {
    topRatedBook = book; // Update top-rated book if current book has a higher rating
  }
});
console.log(topRatedBook);

Using a for...of loop: let topRatedBook = books[0]; // Start with the first book as the top-rated book
for (const book of books) {
  if (book.averageRating > topRatedBook.averageRating) {
    topRatedBook = book; // Update top-rated book if current book has a higher rating
  }
}
console.log(topRatedBook);

13. Getting the top 3 rated books.

To get the three most top-rated books in the books array, you can sort the array in descending order based on the rating property and then use the slice() method to extract the first three objects from the sorted array. Here's an example code: const topRatedBooks = books.sort((a, b) => b.rating - a.rating).slice(0, 3);
console.log(topRatedBooks);

14. Sorting the books by title in ascending order.

books.sort((a, b) => a.title.localeCompare(b.title));
books.forEach(book => {
  console.log(book.title);
});

15. Sorting the books by title in descending order.

books.sort((a, b) => b.title.localeCompare(a.title));
books.forEach(book => {
  console.log(book.title);
});

16. Sorting the books by price in ascending order.

books.sort((a, b) => a.price - b.price);
console.log(books); // Lowest to highest price

17. Sorting the books by price in descending order.

books.sort((a, b) => b.price - a.price);
console.log(books); // Highest to lowest price

18. Printing in HTML template.

Using for...of loop: for (const book of books) {
  const reviewsHTML = book.reviews.map(review => `
    <li>
      <p class="username">${review.username}</p>
      <p class="rating">Rating: ${review.rating}</p>
      <p class="text">${review.text}</p>
      <p class="date">${review.date}</p>
    </li>
  `).join("");
  
  const bookHTML = `
    <div class="book">
      <h2 class="title">${book.title}</h2>
      <p class="author">By ${book.author}</p>
      <p class="published-year">Published in ${book.publishedYear}</p>
      <p class="genre">Genre: ${book.genre.join(", ")}</p>
      <p class="page-count">Page count: ${book.pageCount}</p>
      <p class="price">Price: ${book.price}</p>
      <p class="is-hardcover">${book.isHardcover ? "Hardcover" : "Paperback"}</p>
      <p class="rating">Rating: ${book.rating}</p>
      <ul class="reviews">
        ${reviewsHTML}
      </ul>
    </div>
  `;
  
  console.log(bookHTML);
}

To avoid repeating the book. prefix for each property in the HTML template, you can use destructuring assignment to create variables for each property outside of the template string. Here's an example code:
for (const book of books) {
  const { title, author, publishedYear, genre, pageCount, price, isHardcover, rating, reviews } = book;
  const reviewsHTML = reviews.map(({ username, rating, text, date }) => `
    <li>
      <p class="username">${username}</p>
      <p class="rating">Rating: ${rating}</p>
      <p class="text">${text}</p>
      <p class="date">${date}</p>
    </li>
  `).join("");
  
  const bookHTML = `
    <div class="book">
      <h2 class="title">${title}</h2>
      <p class="author">By ${author}</p>
      <p class="published-year">Published in ${publishedYear}</p>
      <p class="genre">Genre: ${genre.join(", ")}</p>
      <p class="page-count">Page count: ${pageCount}</p>
      <p class="price">Price: ${price}</p>
      <p class="is-hardcover">${isHardcover ? "Hardcover" : "Paperback"}</p>
      <p class="rating">Rating: ${rating}</p>
      <ul class="reviews">
        ${reviewsHTML}
      </ul>
    </div>
  `;
  
  console.log(bookHTML);
}

This code uses destructuring assignment to create variables for each property of both the book and review objects. Inside the map() method for the reviews array, destructuring assignment is used again to create variables for each property of the review object.

The resulting HTML strings for the book and reviews objects are then substituted into the template using string interpolation.

Others

Adding a method in an object.
let person = {
  name: "John",
  age: 30,
  greet: function() {
    return `Hello, my name is ${this.name} and I am ${this.age} years old.`;
  }
};
console.log(person.greet()); // Output: Hello, my name is John and I am 30 years old.

Get all books inStock:
const booksPublishedIn1960AndInStock = books.filter((book) => {
  return book.inStock > 0;
});
if (booksPublishedIn1960AndInStock.length > 0) {
  console.log("The following books match the criteria:");
  booksPublishedIn1960AndInStock.forEach((book) => console.log(book.title));
} else {
  console.log("No books match the criteria.");
}

How to check if there's a book published in 1960 and inStock:
const booksPublishedIn1960AndInStock = books.filter((book) => {
  return book.publishedYear === 1960 && book.inStock > 0;
});

if (booksPublishedIn1960AndInStock.length > 0) {
  console.log("The following books match the criteria:");
  booksPublishedIn1960AndInStock.forEach((book) => console.log(book.title));
} else {
  console.log("No books match the criteria.");
}

Accessing object properties: You can access an object's properties using dot notation or bracket notation. For example:
const person = { name: "John", age: 30 };
console.log(person.name); // "John"
console.log(person["age"]); // 30
Adding or modifying properties: You can add or modify properties of an object using dot notation or bracket notation. For example:
const person = { name: "John", age: 30 };
person.gender = "Male";
person["age"] = 31;
console.log(person); // { name: "John", age: 31, gender: "Male" }

Deleting properties: You can delete properties of an object using the delete keyword. For example:
const person = { name: "John", age: 30 };
delete person.age;
console.log(person); // { name: "John" }
Looping over object properties: You can loop over an object's properties using a for...in loop. For example:
const person = { name: "John", age: 30 };
for (let prop in person) {
  console.log(`${prop}: ${person[prop]}`);
}
// Output:
// name: John
// age: 30

Checking if an object has a property: You can check if an object has a property using the in operator or the hasOwnProperty() method. For example:
const person = { name: "John", age: 30 };
console.log("name" in person); // true
console.log(person.hasOwnProperty("gender")); // false
Copying objects: You can create a shallow copy of an object using the spread operator or the Object.assign() method. For example:
const person = { name: "John", age: 30 };
const copy1 = { ...person };
const copy2 = Object.assign({}, person);
console.log(copy1); // { name: "John", age: 30 }
console.log(copy2); // { name: "John", age: 30 }

Merging objects: You can merge two or more objects into a single object using the spread operator or the Object.assign() method. For example:
const person = { name: "John", age: 30 };
const additionalInfo = { gender: "Male", occupation: "Developer" };
const mergedObj1 = { ...person, ...additionalInfo };
const mergedObj2 = Object.assign({}, person, additionalInfo);
console.log(mergedObj1); // { name: "John", age: 30, gender: "Male", occupation: "Developer" }
console.log(mergedObj2); // { name: "John", age: 30, gender: "Male", occupation: "Developer" }

SEARCH