在 Swift 中同时搜索两个元素?



我有一个这样的结构:

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}
}

如果我想在元素中搜索contentsStructName中的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匹配searchTextcontents中的任何contentName匹配searchTextStructName实例将显示在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
}

如果这不是您想要的,您可能需要更精确地指定搜索条件。


(顺便说一下,namecontents需要是可选的?


(对于更新的示例(

似乎你想要基于角色的搜索,每个角色都需要命中。

使用一点修改的示例:

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]

不过,我不确定这是否是您所期望的,因为您的描述还不够清楚。

最新更新