filter(books, (book) => {
return myFilters.authors.map(a => a.id).includes(book.author_id) &&
myFilters.skus.map(a => a.id).includes(book.sku);
....
You could easily check for the truthiness and perform your expression if it exists. This is known as a Guard. If it doesn't evaluate to true, using the OR operator will default it to true
so your return expression can proceed. It's very similar to a ternary operator.
Consider:
filter(books, (book) => {
return
( myFilters.authors && myFilters.authors.map(a => a.id).includes(book.author_id) || true ) &&
( myFilters.skus && myFilters.skus.map(a => a.id).includes(book.sku) || true );
...
Readability
There are several reasons why you may not want to do this. The main reason may be for readability and maintainability. Your code is short and concise; however, 5 years from now (or even in 2 months) will you be able to quickly know how to modify it or fix a bug? Will someone else?
For that, it's generally better to be more expressive:
filter(books, (book) => {
let has_authors = true // default case if author filters not supplied
let has_skus = true // default case if skus filters not supplied
let {authors, skus} = myFilters // destructuring assignment for code legibility
if ( authors )
has_authors = authors.map(a => a.id).includes(book.author_id)
if ( skus )
has_skus = skus.map(a => a.id).includes(book.sku)
return has_authors && has_skus
}
Of course, this could be further improved using some
to minimize the number of iterations (one loop instead of two) and a function call to reduce the syntax, making it DRYer:
filter(books, (book) => {
let has_authors = true // default case if author filters not supplied
let has_skus = true // default case if skus filters not supplied
let {authors, skus} = myFilters // destructuring assignment for code legibility
if ( authors )
has_authors = hasId( authors, book.author_id )
if ( skus )
has_skus = hasId( skus, book.sku )
return has_authors && has_skus
}
function hasId( array, id ) {
return array.some(v => v.id == id )
}
Working Example of the Above
setup() // create globals and functions
let filtered_books = filter(books, (book) => {
let has_authors = true // default case if author filters not supplied
let has_skus = true // default case if skus filters not supplied
let {authors, skus} = myFilters // destructuring assignment for code legibility
if ( authors )
has_authors = hasId( authors, book.author_id )
if ( skus )
has_skus = hasId( skus, book.sku )
return has_authors && has_skus
})
function hasId( array, id ) {
return array.some(v => v.id == id )
}
console.log(`filtered_books: `, filtered_books)
console.log(`from: `, books)
function setup(){
window.myFilters = {
// authors: [ { id: 7 } ], // <-- uncomment to show a case where no authors match
skus: [
{ id: 3 },
{ id: 5 }
]
}
window.books = [
{author_id:4, sku: 2},
{author_id:5, sku: 3}
]
window.filter = function(array, callback){
return array.filter(callback)
}
}