Arrays 筛选包含字符串和字符串数组的结构对象

Arrays 筛选包含字符串和字符串数组的结构对象,arrays,swift,struct,Arrays,Swift,Struct,我有一个struct对象,其中包含端口到各自国家/地区的映射 struct countryAndPorts { var country: String? var ports: [String]? } 我有一个数组var countryAndPortsArray=[countryAndPorts](),它为每个国家保存countryAndPort对象 我还有一个数组var filteredArray=[countryAndPorts](),它根据用户的搜索查询保存过滤后的coun

我有一个struct对象,其中包含端口到各自国家/地区的映射

struct countryAndPorts {
    var country: String?
    var ports: [String]?
}
我有一个数组
var countryAndPortsArray=[countryAndPorts]()
,它为每个国家保存
countryAndPort
对象

我还有一个数组
var filteredArray=[countryAndPorts]()
,它根据用户的搜索查询保存过滤后的
countryAndPortsArray
对象

我正在使用此功能过滤countryAndPortsArray

func filteredContent(searchKey: String) {
    filteredArray = countryAndPortsArray.filter {
      !($0.ports?.filter{
           $0.range(of: searchKey, options: .caseInsensitive, range: 
           nil, locale: nil) != nil || 
           $0.localizedCaseInsensitiveCompare(searchKey) == .orderedSame
          }.isEmpty ?? true) || 
       $0.country?.localizedCaseInsensitiveContains(searchKey) ?? true
}
我的问题是由于
filterDarray
包含同一国家/地区内的每个端口,而不管用户的搜索键是否与特定端口匹配

例如,如果用户搜索“Paris”,则
filteredArray
将包含法国的每个港口。如果用户搜索“巴塞罗那”,则
过滤器Darray
将包含西班牙的每个港口

预期结果应仅包含与“巴塞罗那”或“巴黎”匹配的港口,而不是同一国家内的所有其他港口

更新

用例:

var france = countryAndPorts(country: "France", ports: 
["monaco","paris","ajaccio","lyon"])

var spain = countryAndPorts(country: "Spain", ports: ["barcelona", 
"madrid", "catalan"])

var countryAndPortsArray = [france,spain]
如果我搜索巴塞罗那的
countryAndPortsArray
,它将返回
[“巴塞罗那”、“马德里”、“加泰罗尼亚”]
。但是我希望它只返回
[“巴塞罗那”]

这是我的tableview代理,以防它更清楚地说明我的问题

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
}

我写的解决方案,但它不是完美的。但它仍然返回了预期的结果

struct countryAndPorts {
    var country: String?
    var ports: [String]?

    func getPort(_ withName: String) -> [String]? {
        return ports?.filter{$0.lowercased() == withName.lowercased()}
    }
}
首先,我们可以编辑结构以获取首选结果

struct countryAndPorts {
    var country: String?
    var ports: [String]?

    func getPort(_ withName: String) -> [String]? {
        return ports?.filter{$0.lowercased() == withName.lowercased()}
    }
}
而不是输出函数来过滤数据。它不是完美的,但它可以工作。它可以减少
flatMap
调用的数量

func fetch(port withName: String, from ports: [countryAndPorts]) -> [String]? {
    return ports.map{$0.getPort(withName)}.flatMap{$0}.filter{($0?.count)! > 0}.flatMap{$0}.first
}
结果:

fetch(port: "madrid", from: countryAndPortsArray) // ["madrid"]?

您能提供一个小数据示例并给出预期结果吗?@Oleggordichuk updatedHi谢谢您的回答。虽然我已经成功地编写了一个工作完美的函数,但我仍然会测试您的答案,然后再回复您。