UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

DAY 35 Project 7 Challenge - Filtering the Petitions Array using .contains

Forums > 100 Days of Swift

Hello

I see the clue, but I am still stuck.

I get an Xcode error: No exact matches in call to subscript

func filterPetitionsArray(_ word:String){

      for i in petitionsArray {
          let petition = petitionsArray[i]  //Xcode error: No exact matches in call to subscript 
          if petition.body.contains(word) || petition.title.contains(word){
              filteredPetitionsArray.append(petition)
          }
      }
          petitionsArray = filteredPetitionsArray
  }

Does Anyone have the solution?

Many thanks!

3      

Kitty posts a code snip and would like a solution, but perhaps would settle for some clues?

I get an Xcode error: No exact matches in call to subscript
Does Anyone have the solution?

The compiler gives you a great clue! == subscript ==

But this clue leads to a discussion about variable names. Take a breath, and buckle up!

You're trying to make an assignment here...

let petition = petitionsArray[i]  //Xcode error: No exact matches in call to subscript 

The compiler complains about the subscript, which you've named i

Basic Language

Last century, a beginner's language called Basic used the convention that any variable starting with the characters i, j, k, l, m, or n should be considered an integer, most often used as counters in a loop. It had this convention because the word integer starts with IN. Or so the legend is told by the elders.

// Basic loop
10 let i = 0
20 if i > 10 then goto 70
30 print "Hello Swift Programmers of the Future"
40 i = i + 1
50 goto 20
60 REM --- END OF LOOP
70 print "Thanks for the memories."

Anyone who saw the letter i, or the letter jin a Basic program just knew that it was an integer and probably was a counter. But in your code snip, what do you thinki is? Is it a counter? It is a number between 1 and the number of petitions in your petitionsArray ?

How can you check? Of course you probably should use a simple print() statement to reveal the contents of i
[PUN WARNING] It might be eye opening! Ha! See what I did there??

Indeed this is a perfect case study showing why Swift developers should go out of their way to use descriptive variable names in code. I think you tricked yourself into believing that i is an index into the array, when it's not. Please! Start the habit now and use descriptive names for your Swift variables.

Your code:

// what value does i get here?
// one way to find out is to hold command key and hover the mouse over the letter i,
// Click your mouse, when the cursor changes to a question mark -->  ?
for i in petitionsArray {
          let petition = petitionsArray[i]  //Xcode error: No exact matches in call to subscript 
          // ..... snip .........
      }

When you press command and hover your mouse over the var, it changes to a question mark --> ? Click to reveal details. You'll see that the compiler infers that i is a Petition object, NOT an index.

Instead, consider the following:

// Simple struct to define a petition
struct Petition {
    let body: String
    let title: String

    func bodyContains(_ searchPhrase: String) -> Bool {
        body.contains(searchPhrase)  // <-- Return true or false
    }
}

// Sample data for testing
let petitionsArray = [
    Petition(body: "Petition 1 description", title: "Petition 1"),
    Petition(body: "Petition 2 description Calamari", title: "Calamari Petition 2"),
    Petition(body: "Petition 3 description", title: "Petition 3"),
]

func filterPetitionsArray(for word: String) -> [Petition] {
    var filteredPetitions: [Petition] = []  // initialize
    // Read this like a sentence!
    // for every petition in the petitionsArray ......
    for petition in petitionsArray {
        if petition.bodyContains(word) || petition.title.contains(word){
            filteredPetitions.append(petition)
        }
    }
    return filteredPetitions
}

let calamariPetitions = filterPetitionsArray(for: "Calamari")
print (calamariPetitions.first!.title)  // Any results?

Keep coding!

Please return and let us know what you learned.

3      

hello evry one this is my solution it work just fine do you have any remarques for me


class ViewController: UITableViewController {

    var petitions = [Petition]()
    var petitionsFiltred : [Petition]?
    .
    .
    .
    override func viewDidLoad() {
    .
    .
     navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .search, target: self, action: #selector(filterTapped))
     }
     .
     .
     .

@objc func filterTapped(){
        let ac = UIAlertController(title: "Filter the petitions", message:"Enter your keywords to filter", preferredStyle: .alert)
        ac.addTextField()
        let filterAction = UIAlertAction(title: "Filter", style: .default) { [weak self,weak ac] action in
            guard let keyword = ac?.textFields?[0].text else {return}
            self?.filter(keyword)
        }
        ac.addAction(filterAction)
        present(ac, animated: true)
    }
    func filter(_ keyword : String){
        if keyword == "" {
            petitionsFiltred = petitions
        }else{
            petitionsFiltred = petitions.filter({ petition in
                petition.body.contains(keyword) || petition.title.contains(keyword)
            })
        }
        self.tableView.reloadData()
    }

3      

Hacking with Swift is sponsored by Essential Developer

SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until April 28th.

Click to save your free spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.