我有一个这样的结构:
struct StructName {
var name: String?
var contents: [Content]?
}
Content
看起来像这样:
struct Content {
var contentName: String?
}
现在我只是在我的StructName
数组中搜索names
var array = [StructName]()
func searchBar(_ searchBar: UISearchBar, textDidChange searchText:String) {
var filteredArray = array.filter { $0.name?.range(of: searchText, options: [.caseInsensitive]) != nil}
}
如果我想在元素中搜索contents
与StructName
中的name
同时进行搜索,我将如何处理?
如果我这样构建它:
let contentA = [Content(contentName: "Content_1"), Content(contentName: "Content_2")]
let contentB = [Content(contentName: "Content_1"), Content(contentName: "Content_2")]
array[0] = (StructName(name: "Name_1", contents: contentA))
array[1] = (StructName(name: "Name_2", contents: contentB))
我在搜索文本中写了"NC",它应该返回所有内容,因为"Name_1"和"Name_2"中有一个"N",在"Content_1"和"Content_2"中有一个"C"。
filteredArray
示例:
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
filteredArray = array.filter{ elements in
var result = false
elements.contents.forEach{ content in
if (content.contentName.lowercased().contains(searchText.lowercased()) ) {
result = true
}
}
if (content.name?.lowercased().contains(searchText.lowercased()))!{
result = true
}
return result
}
}
请注意,这不会像我描述的那样同时搜索。
如果要筛选并查找内容数组项与搜索栏文本比较的 StructNames,请查看此代码
struct Content {
var contentValue: String
}
struct StructName{
var name: String?
var contents: [Content]?
}
var array = [ StructName(name: "test1", contents: [ Content(contentValue: "contentValue1"), Content(contentValue: "contentValue2"), Content(contentValue: "searchedText") ]) ]
let searchedText = "searchedText"
let filteredArray = array.filter{ structName in
var result = false
structName.contents?.forEach{ content in
if (content.contentValue.lowercased().contains(searchedText.lowercased()) ) {
result = true
}
}
return result
}
您对"同时">一词的用法不够清晰,无法描述您期望的搜索结果类型。
我假设,
当(且仅当(name
匹配searchText
或contents
中的任何contentName
匹配searchText
,StructName
实例将显示在filteredArray
中。
(匹配的定义类似于帖子中的name
。
然后你可以写这样的东西:
var filteredArray = array.filter {
$0.name?.range(of: searchText, options: .caseInsensitive) != nil
|| $0.contents?.contains {content in content.contentName?.range(of: searchText, options: .caseInsensitive) != nil} == true
}
如果这不是您想要的,您可能需要更精确地指定搜索条件。
(顺便说一下,name
或contents
需要是可选的?
(对于更新的示例(
似乎你想要基于角色的搜索,每个角色都需要命中。
使用一点修改的示例:
var array = [StructName]()
let contentA = [Content(contentName: "Content_1"), Content(contentName: "Content_2")]
let contentB = [Content(contentName: "Content_3"), Content(contentName: "Content_4")]
array.append(StructName(name: "Name_1", contents: contentA))
array.append(StructName(name: "Name_2", contents: contentB))
有一些调试帮助:
extension StructName: CustomStringConvertible {
var description: String {
return "(name ?? ""):(contents?.map{$0.contentName ?? ""}.joined(separator: ";") ?? "")"
}
}
print(array) //->[Name_1:Content_1;Content_2, Name_2:Content_3;Content_4]
你可以写这样的东西:
func searchBar(_ searchBar: UISearchBar, textDidChange searchText:String) {
let filteredArray = array.filter {element in
!searchText.lowercased().contains {searchChar in
!(element.name ?? "").lowercased().contains(searchChar)
&& !(element.contents ?? []).contains {content in (content.contentName ?? "").lowercased().contains(searchChar)}
}
}
print(filteredArray)
}
输出示例:
searchBar(UISearchBar(), textDidChange: "NC") //->[Name_1:Content_1;Content_2, Name_2:Content_3;Content_4]
searchBar(UISearchBar(), textDidChange: "1") //->[Name_1:Content_1;Content_2]
searchBar(UISearchBar(), textDidChange: "2") //->[Name_1:Content_1;Content_2, Name_2:Content_3;Content_4]
searchBar(UISearchBar(), textDidChange: "12") //->[Name_1:Content_1;Content_2]
不过,我不确定这是否是您所期望的,因为您的描述还不够清楚。