在 [(String, Array<String>)] 上应用 NSPredicate
Apply NSPredicate on [(String, Array<String>)]
我有以这种方式存储的数据,
var data = [(String, Array<String>)]()
示例数据:
[(A, [Apple, Andy, Android]), (B, [Banana, Breakfast])]
我正在尝试使用 Predicate 对此数据应用搜索过滤器,
这是我尝试过但失败了的方法,
func updateSearchResultsForSearchController(searchController: UISearchController) {
let searchPredicate = NSPredicate(format: "SELF CONTAINS[c] %@", searchController.searchBar.text)
let array = (data as NSArray).filteredArrayUsingPredicate(searchPredicate)
data = array as! [(String, Array<String>)]
//reload tableView with fresh data
self.tableView.reloadData()
}
它失败了,因为我试图将我的 data
转换为 NSArray 以应用过滤器,然后尝试将过滤后的数组转换回我想要的格式。 (我知道这种转换是行不通的,这只是为了让你们了解我正在尝试做的事情。)
我的问题是如何对 data
的字符串数组应用搜索过滤器?
例如,如果搜索词是 "an",data
应该过滤到
[(A, [Andy, Android]), (B, [Banana])]
由于您的数组包含元组,而不是使用 NSPredicate
,您可以使用以下方法过滤数据:
func getFilteredData(data : [(String, Array<String>)], ltrToCompare : String) -> [(String, Array<String>)]
{
// For keeping the filtered result
var returnData = [(String, Array<String>)]()
// Looping through parent array
for (letter, arr) in data
{
// Filters the internal array [String]
let filter = arr.filter()
{
return [=10=].lowercaseString.rangeOfString(ltrToCompare.lowercaseString) != nil
}
// Checks whether the inner array filtering returns any element
if (filter.count != 0)
{
returnData.append((letter, filter));
}
}
return returnData
}
从以下位置调用该方法:
func updateSearchResultsForSearchController(searchController: UISearchController)
{
data = getFilteredData(data, ltrToCompare: searchController.searchBar.text)
//reload tableView with fresh data
self.tableView.reloadData()
}
map()
和 filter()
(Swift 1.2) 的可能解决方案:
let data = [("A", ["Apple", "Andy", "Android"]), ("B", ["Banana", "Breakfast"])]
let searchText = "an"
let filtered = map(data) {
([=10=], .filter {
[=10=].rangeOfString(searchText, options: .CaseInsensitiveSearch) != nil
})
}.filter { !isEmpty() }
println(filtered)
// [(A, [Andy, Android]), (B, [Banana])]
第一个 map()
根据搜索文本将每个 (letter, words)
元组映射到 (letter,
filteredWords)
。
随后的 filter()
然后删除 filteredWords
为空的元组。
Swift 2:
只需要稍作改动
let filtered = data.map {
([=11=], .filter {
[=11=].rangeOfString(searchText, options: .CaseInsensitiveSearch) != nil
})
}.filter { !.isEmpty }
我有以这种方式存储的数据,
var data = [(String, Array<String>)]()
示例数据:
[(A, [Apple, Andy, Android]), (B, [Banana, Breakfast])]
我正在尝试使用 Predicate 对此数据应用搜索过滤器,
这是我尝试过但失败了的方法,
func updateSearchResultsForSearchController(searchController: UISearchController) {
let searchPredicate = NSPredicate(format: "SELF CONTAINS[c] %@", searchController.searchBar.text)
let array = (data as NSArray).filteredArrayUsingPredicate(searchPredicate)
data = array as! [(String, Array<String>)]
//reload tableView with fresh data
self.tableView.reloadData()
}
它失败了,因为我试图将我的 data
转换为 NSArray 以应用过滤器,然后尝试将过滤后的数组转换回我想要的格式。 (我知道这种转换是行不通的,这只是为了让你们了解我正在尝试做的事情。)
我的问题是如何对 data
的字符串数组应用搜索过滤器?
例如,如果搜索词是 "an",data
应该过滤到
[(A, [Andy, Android]), (B, [Banana])]
由于您的数组包含元组,而不是使用 NSPredicate
,您可以使用以下方法过滤数据:
func getFilteredData(data : [(String, Array<String>)], ltrToCompare : String) -> [(String, Array<String>)]
{
// For keeping the filtered result
var returnData = [(String, Array<String>)]()
// Looping through parent array
for (letter, arr) in data
{
// Filters the internal array [String]
let filter = arr.filter()
{
return [=10=].lowercaseString.rangeOfString(ltrToCompare.lowercaseString) != nil
}
// Checks whether the inner array filtering returns any element
if (filter.count != 0)
{
returnData.append((letter, filter));
}
}
return returnData
}
从以下位置调用该方法:
func updateSearchResultsForSearchController(searchController: UISearchController)
{
data = getFilteredData(data, ltrToCompare: searchController.searchBar.text)
//reload tableView with fresh data
self.tableView.reloadData()
}
map()
和 filter()
(Swift 1.2) 的可能解决方案:
let data = [("A", ["Apple", "Andy", "Android"]), ("B", ["Banana", "Breakfast"])]
let searchText = "an"
let filtered = map(data) {
([=10=], .filter {
[=10=].rangeOfString(searchText, options: .CaseInsensitiveSearch) != nil
})
}.filter { !isEmpty() }
println(filtered)
// [(A, [Andy, Android]), (B, [Banana])]
第一个 map()
根据搜索文本将每个 (letter, words)
元组映射到 (letter,
filteredWords)
。
随后的 filter()
然后删除 filteredWords
为空的元组。
Swift 2:
只需要稍作改动let filtered = data.map {
([=11=], .filter {
[=11=].rangeOfString(searchText, options: .CaseInsensitiveSearch) != nil
})
}.filter { !.isEmpty }