如何过滤包含字符串和数组的结构?
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{ [=12=] }.filter{[=12=].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" 作为搜索字符串 returns "vlone" 和 "vlore"。 Vlone 和 Vlore 都是阿尔巴尼亚的港口
Result yielded using vlone as search string
然而,所需的输出应仅包括 "vlone",而忽略阿尔巴尼亚的所有其他港口,因为用户的查询是特定的。
第二种情况是使用 "barcelona" 作为搜索关键字。它 returns 结果包含西班牙的每个港口,但是所需的输出应该只包含巴塞罗那。
Results using barcelona as search key
如果你想过滤数组以找到任何具有匹配国家或端口的条目,那么你可以这样做:
func filteredContent(searchKey: String) {
filteredArray = countryAndPortsArray.filter {
[=10=].country?.lowercased().range(of: searchKey) != nil ||
!([=10=].ports?.filter {
[=10=].lowercased().range(of: searchKey) != nil
}.isEmpty ?? true)
}
}
我们来分解一下。顶层是对 countryAndPortsArray
数组上的 filter
的调用。过滤器由两部分组成。 1) 检查国家是否包含搜索文本,以及 2) 检查端口是否包含搜索文本。
第一次检查完成于:
[=11=].country?.lowercased().range(of: searchKey) != nil
这是你已经拥有的部分。
第二次检查完成:
!([=12=].ports?.filter {
[=12=].lowercased().range(of: searchKey) != nil
}.isEmpty ?? true)
由于 ports
是一个数组,过滤器被用来查看是否有任何端口包含搜索文本。 isEmpty
正在检查结果匹配端口的过滤器列表是否为空。由于 ports
是可选的,因此使用 ?? true
意味着匹配端口列表就好像是空的一样。 !
否定结果。因此,如果匹配列表为空(或 ports
为 nil
),则 true
取反为 false
,表示没有匹配端口。
这两项检查使用标准逻辑 "or" 运算符组合 ||
,这意味着只有两项检查中的一项为真,顶级过滤器才能匹配该记录。
基本上这是一个包含国家及其港口的结构对象
struct countryAndPorts {
var country: String?
var ports: [String]?
}
这些是包含映射到其端口的每个国家/地区的数组。过滤后的数组应按国家或港口保存过滤结果。
var countryAndPortsArray = [countryAndPorts]()
var filteredArray = [countryAndPorts]()
目前,以下函数成功生成了使用国家/地区作为搜索关键字的过滤结果
func filteredContent(searchKey: String) {
filteredArray = countryAndPortsArray.flatMap{ [=12=] }.filter{[=12=].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" 作为搜索字符串 returns "vlone" 和 "vlore"。 Vlone 和 Vlore 都是阿尔巴尼亚的港口
Result yielded using vlone as search string
然而,所需的输出应仅包括 "vlone",而忽略阿尔巴尼亚的所有其他港口,因为用户的查询是特定的。
第二种情况是使用 "barcelona" 作为搜索关键字。它 returns 结果包含西班牙的每个港口,但是所需的输出应该只包含巴塞罗那。
Results using barcelona as search key
如果你想过滤数组以找到任何具有匹配国家或端口的条目,那么你可以这样做:
func filteredContent(searchKey: String) {
filteredArray = countryAndPortsArray.filter {
[=10=].country?.lowercased().range(of: searchKey) != nil ||
!([=10=].ports?.filter {
[=10=].lowercased().range(of: searchKey) != nil
}.isEmpty ?? true)
}
}
我们来分解一下。顶层是对 countryAndPortsArray
数组上的 filter
的调用。过滤器由两部分组成。 1) 检查国家是否包含搜索文本,以及 2) 检查端口是否包含搜索文本。
第一次检查完成于:
[=11=].country?.lowercased().range(of: searchKey) != nil
这是你已经拥有的部分。
第二次检查完成:
!([=12=].ports?.filter {
[=12=].lowercased().range(of: searchKey) != nil
}.isEmpty ?? true)
由于 ports
是一个数组,过滤器被用来查看是否有任何端口包含搜索文本。 isEmpty
正在检查结果匹配端口的过滤器列表是否为空。由于 ports
是可选的,因此使用 ?? true
意味着匹配端口列表就好像是空的一样。 !
否定结果。因此,如果匹配列表为空(或 ports
为 nil
),则 true
取反为 false
,表示没有匹配端口。
这两项检查使用标准逻辑 "or" 运算符组合 ||
,这意味着只有两项检查中的一项为真,顶级过滤器才能匹配该记录。