2016-03-15 51 views
0
let searchResultItem1 = SearchResult() 
searchResultItem1.type = "contact" 
searchResultItem1.typeTitle = "CONTACTS" 
searchResultItem1.results = ["Joe" , "Smith" , "Alan" , "Nick" , "Jason"] 

let searchResultItem2 = SearchResult() 
searchResultItem2.type = "address" 
searchResultItem2.typeTitle = "ADDRESS" 
searchResultItem2.results = ["829 6th Street North Fullerton" , "669 Windsor Drive Randallstown" , "423 Front Street Lacey"] 
searchResults.append(searchResultItem1) 
searchResults.append(searchResultItem2) 

當我搜索「人」我期待其結果返回一個信息搜索結果「[艾倫]」,並用它的結果另一個信息搜索結果「[」 669溫莎驅動器的Randallstown」 ]「器陣列中夫特

我試過下面的過濾器,但是返回空數組。

let results = searchResults.filter({$0.results.contains("al")}) 

回答

2

正如其他答案指出的那樣,您正在搜索具有值「al」的項目的結果數組。什麼你想實際上是返回結果的數組,縮小到只有那些匹配:

struct SearchResult { 
    let type:String 
    let typeTitle:String 
    let results:[String] 
} 

let searchResultItem1 = SearchResult(
    type: "contact", 
    typeTitle: "CONTACTS", 
    results: ["Joe" , "Smith" , "Alan" , "Nick" , "Jason"] 
) 

let searchResultItem2 = SearchResult(
    type:"address", 
    typeTitle: "ADDRESS", 
    results:["829 6th Street North Fullerton" , "669 Windsor Drive Randallstown" , "423 Front Street Lacey"] 
) 

var searchResults = [ searchResultItem1, searchResultItem2 ] 

現在,話又說回來,爲了方便,定義不區分大小寫包含函數的字符串:

extension String { 
    func containsIgnoreCase(substring:String) -> Bool { 
     return rangeOfString(
      substring, 
      options: .CaseInsensitiveSearch, 
      range: startIndex..<endIndex, 
      locale: nil)?.startIndex != nil 
    } 
} 

請注意,字符串已經有一個contains函數,它只是區分大小寫,但如果這是足夠的,你甚至不需要定義你自己的。現在

,您可以使用map擺脫不包含搜索字符串的結果:

searchResults = searchResults.map({ 
    return SearchResult(
     type: $0.type, 
     typeTitle: $0.typeTitle, 
     results: $0.results.filter({ 
      $0.containsIgnoreCase("al") 
     }) 
    ) 
}) 

而且,想必,你也想消除沒有實際結果的任何信息搜索結果,所以使用過濾器:

searchResults = searchResults.filter { $0.results.count > 0 } 

當然,整個事情可以串成一個表達:

searchResults = searchResults.map({ 
    return SearchResult(
     type: $0.type, 
     typeTitle: $0.typeTitle, 
     results: $0.results.filter({ 
      $0.contains("al") 
     }) 
    ) 
}).filter { $0.results.count > 0 } 

而且,你都不可能再利用flatMap,這就好比map,但消除了任何nil值減少一些重複的:

searchResults = searchResults.flatMap { 
    let results = $0.results.filter { $0.containsIgnoreCase("al") } 
    if results.count > 0 { 
     return SearchResult(type: $0.type, typeTitle: $0.typeTitle, results: results) 
    } else { 
     return nil 
    } 
} 
3

在您filter$0.results,在每個例如:精確匹配它的參數,而不是一個爭論的子

對象

["Joe" , "Smith" , "Alan" , "Nick" , "Jason"] 
["829 6th Street North Fullerton" , "669 Windsor Drive Randallstown" , "423 Front Street Lacey"] 

Array.contains(_)功能進行搜索,以獲取每個整個數組包含一個帶有子字符串「al」的字符串元素,使用:

let results = searchResults.filter({$0.results.filter({$0.rangeOfString("al") != nil}).count > 0}) 

另外,獲得只與子「人」,使用字符串:

let results = searchResults.map{ $0.results }.reduce([], combine: {$0 + $1}).filter { $0.rangeOfString("al") != nil } 

注意,這將不符合「阿蘭」,因爲rangeOfString是區分大小寫的。

+0

是的,你是對的。 – Nassif

1

您的過濾器檢查結果數組是否包含「al」的條目,而不是結果中的任何字符串是否包含「al」。您需要過濾結果數組並使用過濾的結果數組構造一個新的SearchResult。

我可能會扁平化一個函數,它過濾輸入SearchResult的結果數組並返回一個可選項,具體取決於是否找到任何匹配項。

+0

您可以請一個解決方案的幫助。 – Nassif

+0

大衛貝瑞最終代碼塊是我想到的。 –