6

Hi I have an array of type Book objects and I'm trying to return all the Books filtered by the tags attribute. For example

var books = [

(title = "The Da Vinci Code", tags = "Religion, Mystery, Europe"), 
(title = "The Girl With the Dragon Tatoo", tags = "Psychology, Mystery, Thriller"), 
(title = "Freakonomics", tags = "Economics, non-fiction, Psychology")

}]

and I want to find the books associated with the tags Psychology, (title = "The Girl With the Dragon Tatoo", tag = "Psychology, Mystery, Thriller") and (title = "Freakonomics", tags = "Economics, non-fiction, Psychology"), how would I do that?

3
  • Possible duplicate of Filter Array of [AnyObject] in Swift Commented Sep 24, 2018 at 0:00
  • 1
    Start by using a proper data model. Define a struct with a title property and a property for tags that is an array of strings. Using a tuple and having your tags as a single string is a poor choice of data model and makes all of your tasks more difficult. Commented Sep 24, 2018 at 0:00
  • 2
    Possible duplicate of Filter array of tuples in swift Commented Sep 24, 2018 at 0:23

3 Answers 3

16

So I quickly did this to help out, if someone can improve that's fine I'm just trying to help.

I made a struct for the books

struct Book {
    let title: String
    let tag: [String]
}

Created an array of those

var books: [Book] = []

Which is empty.

I created a new object for each book and appended to books

let dv = Book(title: "The Da Vinci Code", tag: ["Religion","Mystery", "Europe"])
books.append(dv)
let gdt = Book(title: "The Girl With the Dragon Tatoo", tag: ["Psychology","Mystery", "Thriller"])
books.append(gdt)
let fn = Book(title: "Freakonomics", tag: ["Economics","non-fiction", "Psychology"])
books.append(fn)

So you've three objects in the books array now. Try to check with

print (books.count)

Now you want to filter for Psychology books. I filtered the array for tags of Psychology - are filters ok for you?

let filtered = books.filter{ $0.tag.contains("Psychology") } 
filtered.forEach { print($0) }

Which prints the objects with your two Psychology books

Book(title: "The Girl With the Dragon Tatoo", tag: ["Psychology", "Mystery", "Thriller"])

Book(title: "Freakonomics", tag: ["Economics", "non-fiction", "Psychology"])

Sign up to request clarification or add additional context in comments.

9 Comments

Don't forget that Swift it is a type inferred language there is no need to explicitly declare your types 99% of the time. Btw you should declare the struct properties as constants
I believe he is saying we can use the form let dv = Book(title: "The Da Vinci Code", tag: ["Religion","Mystery", "Europe"]) for each book
and struct Book { let title: String let tag: [String] }
Note that your filter count == 1 is very bad it will iterate the whole array even if it finds the element at the first index. change it to books.filter{ $0.tag.contains( "Psychology")} which will provide an early exit in case it matches it
Thanks, this is more feedback than I've had in 14 months of working as a developer
|
1

Representing the books as an array of tuples with named parameters title and tags for book title and tags respectively.

let books:[(title:String, tags:String)] = [

    (title: "The Da Vinci Code", tags: "Religion, Mystery, Europe"),
    (title: "The Girl With the Dragon Tatoo", tags: "Psychology, Mystery, Thriller"),
    (title: "Freakonomics", tags: "Economics, non-fiction, Psychology")

]

You want to search for tag Psychology

let searchedTag = "Psychology"

We can use filter function to filter out the items in the books array that only contains the tag we are looking for.

let searchedBooks = books.filter{ $0.tags.split(separator: ",").map{ return $0.trimmingCharacters(in: .whitespaces) }.contains( searchedTag ) }

print(searchedBooks)

Inside the filter method, we have created an array of tag items from book tags using split(separator: Character) method. Next, using map function, we remove the leading and trailing whitespaces from each tag. Finally, using .contains(element) method, we test if the tag we are looking for is in this array. Only the tuples passing this test are returned and the others will be filtered out.

The result is:

[(title: "The Girl With the Dragon Tatoo", tags: "Psychology, Mystery, Thriller"), (title: "Freakonomics", tags: "Economics, non-fiction, Psychology")]

Comments

1

I think this is more useful for lack of wrong typing situation.

books.filter( { $0.tag.range(of: searchText, options: .caseInsensitive) != nil}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.