Reputation: 469
What is the most efficient way of filtering an array of objects based on one of their properties, using an array of values? I could iterate through the items, but I can't help thinking there's a really efficient way using Array.filter and Array.contains - I'm just not proficient enough with Swift to be able to put the pieces together.
For example, if I have an array containing Book objects, each of which has a String author property, how would I filter it to show only books by John Smith, Arthur Price or David Jones?
Something along the lines of:
Class Book {
var author : String = String()
}
var books : Array = [Book]()
//books added elsewhere
let authors = ["John Smith", "Arthur Price", "David Jones"]
let filteredBooks = books.filter({authors.contains({($0 as Book).author})})
Upvotes: 15
Views: 24009
Reputation: 52227
You could also use something like
let authorsAndBooks = authors.map {
(authorName) -> (String, [Book])
in (authorName,
allBooks.filter({ $0.author == authorName })
)
}
This will array of tuples with the first element being the author name and the second element an array of his books, in case an author wrote more than one book.
Upvotes: 6
Reputation: 469
This is what I have working in a playground, any reason why this is no good?
class Book {
var author = String()
init(author:String){
self.author = author
}
}
var allBooks: [Book] = []
allBooks.append(Book(author: "John Smith"))
allBooks.append(Book(author: "Arthur Price"))
allBooks.append(Book(author: "David Jones"))
allBooks.append(Book(author: "Somebody Else"))
let authors = ["Arthur Price", "David Jones"]
let filteredBooks = allBooks.filter({authors.contains($0.author)})
filteredBooks // [{author "Arthur Price"}, {author "David Jones"}]
Upvotes: 20
Reputation: 10951
I'd recommend you make an index of books by author:
let book = Book(author: "Arsen")
let bookIndex = [book.author: [book]]
And now you have incredible fast access to your book filtered by author:
bookIndex["Arsen"] // => [Books]
For multiple authors:
var results = [Book]()
for author in authors {
if let books = bookIndex[author] {
results += books
}
}
results
Upvotes: 3