简体   繁体   English

过滤包含字符串和字符串数组的结构对象

[英]Filtering a struct object containing a string and array of strings

I have a struct object holding a mapping of ports to their respective countries. 我有一个结构对象,其中包含端口到其各自国家的映射。

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

I have an array var countryAndPortsArray = [countryAndPorts]() that holds countryAndPort object for every country. 我有一个数组var countryAndPortsArray = [countryAndPorts]() ,它保存每个国家的countryAndPort对象。

I also have an array var filteredArray = [countryAndPorts]() which holds filtered countryAndPortsArray objects depending on the user's search query 我还有一个数组var filteredArray = [countryAndPorts]() ,该countryAndPortsArray根据用户的搜索查询保存已过滤的countryAndPortsArray对象

I am filtering countryAndPortsArray with this function 我正在使用此功能过滤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
}

My problem is the result of filteredArray contains every port within the same country regardless the user's search key matches a particular port. 我的问题是, filteredArray的结果是包含同一个国家/地区中的每个端口,无论用户的搜索键是否匹配特定端口。

For example, if a user searches for "Paris", the filteredArray will contain every port in France. 例如,如果用户搜索“巴黎”,则filteredArray将包含法国的每个端口。 If a user searches "barcelona", the filteredArray will contain every port in Spain. 如果用户搜索“巴塞罗那”,则filteredArray将包含西班牙的每个端口。

The desired result should only contain ports matching "barcelona" or "paris" and not every other port within the same country. 期望的结果应仅包含与“巴塞罗那”或“巴黎”匹配的端口,而不应包含同一国家/地区中的所有其他端口。

UPDATE UPDATE

Use Case: 用例:

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

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

var countryAndPortsArray = [france,spain]

if i search countryAndPortsArray for barcelona, it returns ["barcelona", "madrid", "catalan"] . 如果我在countryAndPortsArray中搜索countryAndPortsArray ,则返回["barcelona", "madrid", "catalan"] However i would want it to only return ["barcelona"] 但是我希望它只返回["barcelona"]

here is my tableview delegates just incase it sheds more light to my question 这是我的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
}

I write solution but it is not perfect. 我写的解决方案,但并不完美。 But still it return expected result. 但是它仍然返回预期结果。

Firstly we could edit structure to fetch as preferred result. 首先,我们可以编辑结构以获取首选结果。

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

    func getPort(_ withName: String) -> [String]? {
        return ports?.filter{$0.lowercased() == withName.lowercased()}
    }
}

Than out function to filter data. 比起过滤数据的功能。 It is not perfect but it works it is possible to reduce amount of flatMap calls. 它不是完美的,但它可以减少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
}

Result: 结果:

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

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

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