2017-09-12 13 views
0

このJSONで一致するキーワードを検索しようとしています。たとえば、タイトル、番号、またはユーザーの配列のいずれかにsamを含むオブジェクトが必要です。私のコードでスワップでJSONを検索

[ 
    { 
     "title":"List of students", 
     "number": "12 stu", 
     "users":[{ 
      "id": 12, 
      "name":"tom" 
     }, 
     { 
      "id": 1, 
      "name":"sam" 
     }] 
    }, 
    { 
     "title":"List of tutors", 
     "number": "2 tut", 
     "users":[{ 
      "id": 1, 
      "name":"John" 
     }, 
     { 
      "id": 1, 
      "name":"Sam" 
     }] 
    } 
] 

、私は唯一のタイトルと番号を検索することができますが、各ユーザーを検索傾けます。

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { 
    arrResf = arrRes.filter({ (item) -> Bool in   
     let heading: NSString = ((item["title"]! as? String)! + (item["number"]! as! String)) as NSString 
     return (heading.range(of: searchText, options: NSString.CompareOptions.caseInsensitive).location) != NSNotFound 
    }) 
    self.tableView.reloadData() 
} 

ユーザーを含めるように検索を拡張するにはどうすればよいですか。

ありがとうございました。

答えて

0
result = array.filter { item in 
    let title = item["title"] as? String ?? "" 
    let number = item["number"] as? String ?? "" 
    let users = (item["users"] as? [[String: Any]]) ?? [] 
    let usersString = users.reduce("") { result, dictionary in 
    [result, dictionary["name"]].flatMap { $0 }.joined(separator: "\t") 
    } 
    let finalString = [title, number, usersString].joined(separator: "\t") 
    return finalString.lowercased().contains(searchTerm.lowercased()) 
} 

は、私はあなたが単一の値に配列を「減らす」役立つ、reduceを使用することになり、辞書の配列です。私がここでやっていることは、配列のすべての辞書を調べて、文字列にnameの値を追加することです。

詳細のカップル:あなたは、可能な場合NSオブジェクトにスウィフトオブジェクトを変換することは避けてください

  • 。それはあなたのコードクリーナーを行います。
  • 強制的にアンラッピングするオプションは使用しないでください。辞書にコード内の「title」の値がない場合、クラッシュします。 ??
  • これを辞書で使用することはできますが、structを作成してJSON辞書から初期化することをおすすめします。
+0

このコードはかなり非効率的です。たとえば、タイトルが一致する場合は、番号を確認したり、ユーザーをスキャンしたりする必要はありません。検索の場合、データの量によってはこの非効率性が顕著になることがあります。 – rmaddy

0

コードには多くの問題があります。 SwiftでNSStringを使用しないでください。オプションを強制的に展開しないでください。次のように

私はあなたのフィルタを実装します:このコードは想定してい

arrResf = arrRes.filter { (item) -> Bool in 
    // Check the title 
    if let title = item["title"] as? String, title.range(of: searchText, options: .caseInsensitive) != nil { 
     return true 
    } 

    // Check the number 
    if let number = item["number"] as? String, number.range(of: searchText, options: .caseInsensitive) != nil { 
     return true 
    } 

    // Check the users name 
    if let users = item["users"] as? [[String:Any]] { 
     for user in users { 
      if let name = user["name"] as? String, name.range(of: searchText, options: .caseInsensitive) != nil { 
       return true 
      } 
     } 
    } 

    return false 
} 

あなたは、タイトル、番号またはユーザーの名前のいずれかのどちらかが検索テキストと一致する任意の項目を返すようにしたいです。ユーザー以来