繁体   English   中英

如何过滤包含字符串和数组的结构?

[英]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作为搜索字符串产生的结果

但是,所需的输出应仅包括“ 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表示充当匹配端口列表为空。 ! 否定结果。 因此,如果匹配列表为空(或portsnil ),则将true否定为false表示没有匹配的端口。

使用标准逻辑“或”运算符||两个检查组合在一起 这意味着对于顶层过滤器以匹配该记录,仅需要两项检查中的一项为真。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM