2017-04-21 11 views
0

は、基本的にこれは、これらがそのポートにマッピングされたそれぞれの国を保持している配列である構造体の国を保持するオブジェクトとそのポート文字列と配列を含む構造体をフィルタリングする方法は?

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とヴロラは、所望の出力のみが「vlone」が含まれ、ユーザが自分のクエリで特定したので、アルバニア内の他のすべてのポートを除外すべきであるしかしアルバニア

で両方のポート

Result yielded using vlone as search string

です。

第2のシナリオでは、「バルセロナ」を検索キーとして使用します。スペインのすべてのポートを含む結果が返されますが、目的の出力にはバルセロナのみが含まれている必要があります。

Results using barcelona as search key

+0

なぜマッピングの構造体を定義しますか? 'var countriesAndPorts = [String:[String]]()'を使い、 'let ports = countriesAndPorts [" Spain "]'を呼んで国のポートを取得してください。 – NRitH

+0

@NRitH辞書より構造が優れています。他のプロパティがあるかもしれませんが、追加できるロジックがあるかもしれません。 – rmaddy

+0

@NRitHオンラインでどこかを見ましたが、それほど考えられませんでした。通常、私は構造体を使用して、クラスではなく複雑なデータ構造を構築します。 –

答えて

0

あなたが一致する国またはポートを持つ任意のエントリを検索し、配列をフィルタリングする場合は、あなたが行うことができます:

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配列にあります。フィルターは2つの部分で構成されています。 1)国に検索テキストが含まれているかどうかを確認し、2)ポートに検索テキストが含まれているかどうかを確認する。

最初のチェックはして行われます:あなたはすでに持っていた部分である

$0.country?.lowercased().range(of: searchKey) != nil 

第2のチェックを用いて行われる:portsため

!($0.ports?.filter { 
    $0.lowercased().range(of: searchKey) != nil 
}.isEmpty ?? true) 

が配列され、フィルタは、ポートのいずれかが検索テキストが含まれているかどうかを確認するために使用されています。 isEmptyは、結果として一致するポートのフィルタリストが空であるかどうかを確認しています。 portsはオプションであるため、?? trueを使用すると、あたかも一致するポートのリストが空であるかのように動作することを意味します。 !は結果を無効にします。一致するリストが空の場合(またはportsnilの場合)、一致するポートがないことを示すtruefalseにネゲートされます。

2つのチェックは、2つだけのチェックのいずれかが最上位レベルのフィルタは、そのレコードに一致する真である必要がある意味標準論理「または」演算子||を使用して合成されます。

+0

@maddyああ生命の節約は、完全に動作します。痛みではありませんが、あなたの解決策を私に教えてもらうのに数分を費やすことができれば、それは素晴らしいことです。これらの上位関数の一般的なハングアップを取得しています。ありがとうございました –

+0

私は解答を更新しました。それは明確ですか? – rmaddy

+0

ありがとうございました。もう一つ、今、私が "ロンドン"を検索すると、それはイングランドと南アフリカのすべての港を持ち出します(明らかに、SAの "イーストロンドン"と呼ばれる港)。 「ロンドン」と一致するポートだけを持ち出すことは可能ですか? –

関連する問題