2017-09-12 5 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"값이 없으면 충돌 방지 옵션을 사용하지 않아야합니다. 충돌이 발생합니다. ??
  • 사전에 사용할 수 있지만, JSON 사전에서 초기화 할 수있는 struct을 만드는 것이 좋습니다.
+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 
} 

당신은 제목, 번호 또는 사용자 이름의 하나가 검색 텍스트와 일치하는 모든 항목을 반환합니다. 사용자 이후