过滤字典中的数组 - Swift

时间:2017-03-27 17:44:23

标签: swift dictionary uisearchbar uisearchcontroller

我正在尝试搜索索引字典,以根据客户端的姓氏返回特定客户端。以下是我正在使用的数据结构。每个客户端对象都有一个名称属性,即String。

var clients = Client.loadAllClients()     //Returns client array
var contacts = [String: [Client]]()      //Indexed clients in a dictionary 
var letters: [String] = [] 

var filteredClient = [Client]()
var shouldShowSearchResults = false
var searchController : UISearchController!   

当我进行索引时,联系人字典会返回:

{A: [Client("Andrew")]}

字母数组返回:

[A]

我正在使用UISearchController来显示已过滤的客户端数组。

func updateSearchResults(for searchController: UISearchController) {
    // how to filter the dictionary 
    self.tableView.reloadData()
}

但是,我不知道如何过滤字典以返回正确的客户列表。我试过用

contacts.filter(isIncluded: ((key: String, value: [Client])) throws -> Bool((key: String, value: [Client])) throws -> Bool)

但我对实施感到非常困惑。我正在使用Xcode 8.0和Swift 3.0。

如果有人能指出我正确的方向,那将非常感激。如果我需要澄清任何事情,请告诉我。先感谢您。完整代码可以在Github

找到

1 个答案:

答案 0 :(得分:2)

主要问题是您使用字典作为数据源数组

我的建议是使用自定义结构作为模型

struct Contact {
   let letter : String
   var clients : [Client]

   init(letter: String, clients : [Client] = [Client]()) {
      self.letter = letter
      self.clients = clients
   } 

   mutating func add(client : Client) {
        clients.append(client)
   }
}

然后创建数据源数组

var contacts = [Contact]()  

和字母数组作为计算属性

var letters : [String] = {
   return contacts.map{ $0.letter }
}

通过字母

对数组进行排序很容易
contacts.sort{ $0.letter < $1.letter }

现在您可以通过这种方式进行搜索/过滤(text是要搜索的文本)

 filteredClient.removeAll()
 for contact in contacts {
     let filteredContent = contact.clients.filter {$0.name.range(of: text, options: [.anchored, .caseInsensitive, .diacriticInsensitive]) != nil }
     if !filteredContent.isEmpty {
         filteredClient.append(filteredContent)
     }
 }

如果您将filteredClient也声明为[Contact]并使用已过滤的项目创建临时Contact个实例,您甚至可以保留这些部分(字母)。

当然,您需要更改所有表视图数据源/委托方法以符合Contact数组,但它是值得的。作为数据源的数组比字典更有效。