字符串数组中不区分大小写的过滤器可搜索文本

Case incensitive filter searchable text in an array of strings

我在一个结构中有一个字符串数组。这会填充一个列表,我使用 .searchable 来过滤那里的元素。我可以在每个项目中按文本、日期或标签过滤它们。全部完成,不考虑大小写。

现在,对于标签,我正在努力寻找过滤它们的正确方法:

let dateFormatter = DateFormatter()

struct LibItem: Codable, Hashable, Identifiable {
    let id: UUID
    var text: String
    var date = Date()
    var dateText: String {
        dateFormatter.dateFormat = "EEEE, MMM d yyyy, h:mm a"
        return dateFormatter.string(from: date)
    }
    var tags: [String] = []
}

final class DataModel: ObservableObject {
    @AppStorage("myapp") public var collectables: [LibItem] = []

    init() {
        self.collectables = self.collectables.sorted(by: {
            [=10=].date.compare(.date) == .orderedDescending
        })
    }

    func sortList() {
        self.collectables = self.collectables.sorted(by: {
            [=10=].date.compare(.date) == .orderedDescending
        })
    }    
}

struct ContentView: View {
    @EnvironmentObject private var data: DataModel
    @State var searchText: String = ""

    var body: some View {
        NavigationView {
            List(filteredItems) { collectable in
                VStack(alignment: .leading) {
                    Spacer()
                    Text(collectable.text).font(.body).padding(.leading).padding(.bottom, 1)
                    Spacer()
                }
            }
            .listStyle(.plain)
            .searchable(
                text: $searchText,
                placement: .navigationBarDrawer(displayMode: .always),
                prompt: "Search..."
            )
        } 
    }

    var filteredItems: [LibItem] {       
        switch selectedItem {
        case 1: // date
            return data.collectables.filter {
                searchText.isEmpty ? true : [=10=].dateText.localizedCaseInsensitiveContains(searchText)
            }
        case 2: //tags <--- here how do I search and filter by, case insensitive?
            return data.collectables.filter {
                searchText.isEmpty ? true : [=10=].tags.contains(searchText)
            }
        default:
            return data.collectables.filter {
                searchText.isEmpty ? true : [=10=].text.localizedCaseInsensitiveContains(searchText)
            }
        }

    }
}

通过暂时将比较的两边都转为小写来比较两个小写的字符串。

您可以在代码中使用的示例:

[=10=].tags.compactMap { [=10=].lowercased() }.contains(searchText.lowercased())

如果需要检查tags的每一项是否包含字符串的部分,需要迭代:

var isTagFound = false
[=11=].tags.compactMap { [=11=].lowercased() }.forEach {
    if [=11=].contains(searchText.lowercased()) {
        isTagFound = true
    }
}

对于严格相等,不区分大小写:

return data.collectables.filter {
   searchText.isEmpty
      ? true
      : [=10=].tags.contains { tag in tag.caseInsensitiveCompare(searchText) == .orderedSame }
}

对于子字符串,可以使用range(of:)方法:

return data.collectables.filter {
   searchText.isEmpty
      ? true
      : [=11=].tags.contains { tag in tag.range(of: searchText, options: .caseInsensitive) != nil }
}

或者,使用您之前已经使用过的localizedCaseInsensitiveContains

return data.collectables.filter {
   searchText.isEmpty
      ? true
      : [=12=].tags.contains { tag in tag.localizedCaseInsensitiveContains(searchText) }
}