[英]How to filter a struct containing a string and an array?
基本上,这是一个包含一个国家及其港口的结构对象
struct countryAndPorts {
var country: String?
var ports: [String]?
}
这些是将每个国家/地区映射到其港口的阵列。 过滤后的数组应按国家或港口保存过滤后的结果。
var countryAndPortsArray = [countryAndPorts]()
var filteredArray = [countryAndPorts]()
当前,以下功能使用国家/地区作为搜索键成功生成了过滤结果
func filteredContent(searchKey: String) {
filteredArray = countryAndPortsArray.flatMap{ $0 }.filter{$0.country?.lowercased().range(of: searchKey) != nil }
}
现在,我的问题是我希望通过使用端口或国家/地区作为搜索关键字来获得过滤结果。 我已尽力而为,但使用端口作为搜索键似乎无法获得理想的结果。 我当前方法的改进将不胜感激。 也欢迎在Objective-C中回答。
//Just incase it's of any use, these are my UITableView delegates
extension SearchDealsViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let count = filteredArray[section].ports?.count {
return count
}
return 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
if let port = filteredArray[indexPath.section].ports?[indexPath.row] {
cell.textLabel?.text = port
}
cell.textLabel?.font = UIFont.systemFont(ofSize: 10)
return cell
}
func numberOfSections(in tableView: UITableView) -> Int {
return filteredArray.count
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
portsFromTextField.text = filteredArray[indexPath.section].ports?[indexPath.row]
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let header = tableView.dequeueReusableCell(withIdentifier: "header")
let tapSectionHeaderGesture = UITapGestureRecognizer(target: self, action: #selector(getCountryText(sender:)))
tapSectionHeaderGesture.numberOfTouchesRequired = 1
tapSectionHeaderGesture.numberOfTapsRequired = 1
header?.addGestureRecognizer(tapSectionHeaderGesture)
if header != nil {
header?.textLabel?.textColor = THEME_COLOUR
header?.textLabel?.font = UIFont.boldSystemFont(ofSize: 12)
header?.textLabel?.text = filteredArray[section].country
}
return header
}
func getCountryText(sender: UITapGestureRecognizer) {
if let country = sender.view as? UITableViewCell {
portsFromTextField.text = country.textLabel?.text
}
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 30
}
-------------------------------- UDPATE ----------------- --------------
目前,输入“ vlone”作为搜索字符串会同时返回“ vlone”和“ vlore”。 Vlone和Vlore都是阿尔巴尼亚的港口
但是,所需的输出应仅包括“ vlone”,而忽略阿尔巴尼亚的所有其他端口,因为用户是特定于其查询的。
第二种情况是使用“巴塞罗那”作为搜索关键字。 它返回一个包含西班牙每个端口的结果,但是所需的输出应仅包含巴塞罗那。
如果要过滤数组以查找具有匹配的国家或地区的任何条目,则可以执行以下操作:
func filteredContent(searchKey: String) {
filteredArray = countryAndPortsArray.filter {
$0.country?.lowercased().range(of: searchKey) != nil ||
!($0.ports?.filter {
$0.lowercased().range(of: searchKey) != nil
}.isEmpty ?? true)
}
}
让我们分解一下。 顶层是对countryAndPortsArray
数组进行filter
的调用。 过滤器由两部分组成。 1)检查该国家/地区是否包含搜索文字,以及2)检查任何端口是否包含搜索文字。
第一步检查完成:
$0.country?.lowercased().range(of: searchKey) != nil
这是您已经拥有的部分。
第二项检查通过以下方式完成:
!($0.ports?.filter {
$0.lowercased().range(of: searchKey) != nil
}.isEmpty ?? true)
由于ports
是一个数组,因此使用过滤器来查看是否有任何端口包含搜索文本。 isEmpty
正在检查匹配端口的结果过滤器列表是否为空。 由于ports
是可选的,因此使用?? true
?? true
表示充当匹配端口列表为空。 !
否定结果。 因此,如果匹配列表为空(或ports
为nil
),则将true
否定为false
表示没有匹配的端口。
使用标准逻辑“或”运算符||
两个检查组合在一起 这意味着对于顶层过滤器以匹配该记录,仅需要两项检查中的一项为真。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.