[英]Swift Combine Compare String
我有一个 function 使用组合提供基于用户输入的结果列表。
例如:如果用户键入rain,它将显示一个结果列表,其中包含单词rain。
数据存储在结构中,我需要先匹配一个元素,如果没有匹配,请尝试匹配另一个元素。
例如:
struct dataSet: Codable, Hashable {
let nameShort: String
let nameLong: String
}
当用户在表单域中输入一个值时,我希望它先查看nameShort,如果没有结果,再查看nameLong。
等式的第二部分是我需要它使用整个字符串进行匹配,但使用单独的单词。
例如:如果用户输入 brown,它应该通过 nameShort 来查找 brown,然后通过 nameLong 来查找 brown。 但是,如果有大量条目匹配 brown 并且用户然后键入 brown chair,我需要它返回匹配这两个值的结果。
同样,如果用户键入 brow chai,它仍应返回 brown chair,因为初始字符与结构中的单词匹配,即使 nameLong 是 Brown - Side Chair。
这是我当前 function 的示例:
func editingChangedName(_ value: String) {
$myName
.debounce(for: 0.3, scheduler: RunLoop.main)
.receive(on: DispatchQueue.global()) // Perform filter on background
.map { [weak self] filterString in
guard filterString.count >= 3, let self = self else { return [] }
return self.nameArray.filter {
$0.nameShort
.lowercased()
.contains(
filterString.lowercased()
) ||
$0.nameLong
.lowercased()
.contains(
filterString.lowercased()
)
}
}
.receive(on: RunLoop.main) // Switch back to main thread
.assign(to: &$allNamesArray)
} // End func
这在表单字段的 onChange 上运行,因此它会不断更新结果。
我试过这样的事情:
let searchString = filterString.lowercased().components(separatedBy: " ")
在保护语句下方,然后从返回中删除 $0.nameShort 和 $0.nameLong ,将其替换为:
searchString.contains(where: $0.nameLong.contains)
但随后所有的结果都变得糟糕透顶。
如果我删除 $0.nameShort 并且只使用 $0.nameLong,并且 change.contains to.hasPrefix 它只会从左到右读取并完全匹配那些存在的字符。 所以,如果我输入 chair,我会得到 0 个结果,而如果我输入 brown,我会得到所有以 brown 开头的结果。
我觉得我很接近,但无法弄清楚如何正确地做到这一点。
在 map 闭合内部试试这个:
let filterComponents = filterString
.lowercased()
.components(separatedBy: " ")
return self.nameArray.filter { name in
return filterComponents.allSatisfy { component in
return name.nameShort.lowercased().contains(component)
|| name.nameLong.lowercased().contains(component)
}
}
使用String.components(separatedBy:)
提取每个单词。 然后调用allSatisfy
检查每个单词是否包含在nameShort
或nameLong
中。
请注意,如果 nameShort 为“brown”且 nameLong 为“chair”,并且您使用“brown chair”作为搜索字符串,则数据集将匹配。 如果您希望所有组件在 nameShort 或 nameLong 中匹配,您必须执行以下操作:
let filterComponents = filterString
.lowercased()
.components(separatedBy: " ")
return self.nameArray.filter { name in
return filterComponents.allSatisfy { component in
return name.nameShort.lowercased().contains(component)
} || filterComponents.allSatisfy { component in
return name.nameLong.lowercased().contains(component)
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.