简体   繁体   中英

Can I use filter to extract values from an array of objects?

I have an array of objects:

const books = [
  {
    title: 'Book',
    author: 'Name'
  },
  {
    title: 'Book2',
    author: 'Name2'
  }
];

I'd like to extract the titles into an array using the filter method. So far I tried this but the array returns with the 2 original objects:

const getTheTitles = function(array) {
   const filteredArray = array.filter(function(book) {
      return book.title;
   })
   return filteredArray;
}

I also tried this but it results in an empty array (not sure why):

const getTheTitles = function(array) {
   const filteredArray = array.filter(function(book) {
      book.title;
   })
   return filteredArray;
}

I understand that this could be accomplished using map. But I am trying to accomplish it using filter.

If you want to get the titles of certain filtered books, then either do it by chaining map to filter , like so:

let filteredBookTitles = books
  .filter(book => book.author === "Some Name")           // first filter (us any criteria here to select only the books you want)
  .map(book => book.title);                              // then get the titles of those filtered books

Demo:

 const books = [{ title: "Animal Farm", author: "George Orwell" }, { title: "Oliver Twist", author: "Charles Dickens" }, { title: "1984", author: "George Orwell" }]; let georgeOrwellBooks = books.filter(book => book.author === "George Orwell") .map(book => book.title); console.log(georgeOrwellBooks);

Or by using a reduce to do both while looping the array only once, like so:

let filteredBookTitles = books.reduce((acc, book) => {   // for each book in the books array
  if(book.author === "Some Name") {                      // if the book matches the criteria
    acc.push(book.title);                                // add its title to the results array
  }

  return acc;
}, []);

Demo:

 const books = [{ title: "Animal Farm", author: "George Orwell" }, { title: "Oliver Twist", author: "Charles Dickens" }, { title: "1984", author: "George Orwell" }]; let georgeOrwellBooks = books.reduce((acc, book) => { if(book.author === "George Orwell") { acc.push(book.title); } return acc; }, []); console.log(georgeOrwellBooks);

You can only use Array#filter to remove items but not to transform them. The filter function is applied to each item. If the function returns true (or anything that is truthy ) the item is kept otherwise it is removed.

Example: keeping only odd numbers:

[1,2,3,4,5].filter(n => n % 2 !== 0);
//=> [1,3,5]

Example: removing false from an array of booleans:

[true,false,true,false].filter(b => b);
//=> [true,true]

What you're trying to do is to transform all items. eg from [{n:1},{n:2},{n:3}] to [1,2,3] . In this case you need Array#map which applies a function to all items and creates a new array with the results:

[{n:1},{n:2},{n:3}].map(o => o.n);
//=> [1,2,3]

Why does this function return all books?

const getTheTitles = function(array) {
  const filteredArray = array.filter(function(book) {
    return book.title;
  })
  return filteredArray;
}

The problem is that your filter function evaluates book.title to decide whether to keep the book object. However all your books have a title and therefore this function is the same as saying "Does this book have a title?"

Why does this function return no books at all?

const getTheTitles = function(array) {
  const filteredArray = array.filter(function(book) {
    book.title;
  })
  return filteredArray;
}

The problem is that your filter function doesn't actually return anything explicitly . When a function has no return statement then it returns undefined by default which is a "falsy" value. This function is the same as saying "Ignore all books"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM