2016-03-15 66 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

大卫贝瑞最终代码块是我想到的。 –