0

I have two initialized and uninitialized arrays as follows:

var colours: [String] = ["Blue", "Red", "Green", "Yellow"]
var numbers: [Int]    = [11, 12, 13, 14]
var coloursFiltered: [String]?
var numbersFiltered: [Int]?

In my search bar, I could filter only one array in the textDidChange function as follows:

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        coloursFiltered = colours.filter({ item -> Bool in
            if searchText.isEmpty { return true }
            return item.lowercased().contains(searchText.lowercased())
        })
        tableView.reloadData()
}

/* Later in the Code */
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return coloursFiltered!.count
}

I need to filter the numbers array as well to match the corresponding indices of the filtered colours array. I cannot do so as I cannot access the current index in the colours.filter function. This is to achieve the following:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
    self.tableView.register(UINib.init(nibName: "ItemTableViewCell", bundle: nil), forCellReuseIdentifier: "ItemTableViewCell")
    
    let cell = self.tableView.dequeueReusableCell(withIdentifier: "ItemTableViewCell", for: indexPath) as! ItemTableViewCell
   
    cell.name.text = "\(coloursFiltered![indexPath.row])"
    cell.code.text = ""\(numbersFiltered![indexPath.row])"   // I need this to work
   
    return cell
}

Is there a way to filter two arrays using the same string?

Ahmed Eid
  • 70
  • 7
  • 1
    Rather than looking for a solution refactor your code to use a struct as suggested by Sh_Khan. Multiple arrays as data source are horrible. – vadian Jun 01 '21 at 12:14
  • I eventually did refactor my code and used a struct model. Thanks for the suggestion. – Ahmed Eid Jun 01 '21 at 12:36

2 Answers2

0

You better have a model

struct Item {
  let color:String
  let number:Int
}

Then

var all = [Item(color:"Blue",number:11),.....]
var coloursFiltered = [Item]()

And filter it instead

coloursFiltered = all.filter({ item -> Bool in
  if searchText.isEmpty { return true }
     return item.color.lowercased().contains(searchText.lowercased())
  })
tableView.reloadData()

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return coloursFiltered.count
} 
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
    self.tableView.register(UINib(nibName: "ItemTableViewCell", bundle: nil), forCellReuseIdentifier: "ItemTableViewCell") 
    let cell = self.tableView.dequeueReusableCell(withIdentifier: "ItemTableViewCell", for: indexPath) as! ItemTableViewCell
    let item = coloursFiltered[indexPath.row]
    cell.name.text = item.color
    cell.code.text = "\(item.number)"  
    return cell
}
Shehata Gamal
  • 98,760
  • 8
  • 65
  • 87
  • I found your solution to be working and quite helpful. Thank you so much. Your solution is also much better in case I needed to filter in more than two classifications/arrays. I found a different and simpler solution that I will post. Let me know what you think of it. – Ahmed Eid Jun 01 '21 at 11:59
0

I tried the answer from @Sh_Khan and it is working and very helpful. Here is a similar approach to the solution that I found in another question inspired by @Aju Antony.

 func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {  
    
    let result = zip(colours, numbers).filter { name, code in
        name.lowercased().contains(searchText.lowercased()) ||
        String(code).contains(searchText.lowercased())
    }
    
    let filteredNames = result.map({ $0.0 })
    let filteredCodes = result.map({ $0.1 })
    
    self.coloursFiltered = filteredNames
    self.numberseFiltered = filteredCodes
    
    tableView.reloadData()
}
Ahmed Eid
  • 70
  • 7