通配符模式匹配:给定一个字符串和一个包含通配符的模式,即*
和?
,其中?
可以匹配输入字符串中的任何单个字符,而{{1} }可以匹配任意数量的字符(包括零个字符),设计一种有效的算法来查找模式是否与完整的输入字符串匹配。
例如:
输入:字符串=“ xyxzzxy”,样式=“ x *** y”
输出:匹配
输入:字符串=“ xyxzzxy”,样式=“ x *** x”
输出:无匹配项
输入:字符串=“ xyxzzxy”,模式=“ x *** x?”
输出:匹配
输入:字符串=“ xyxzzxy”,样式=“ *”
输出:匹配
答案 0 :(得分:1)
借助Foundation类(尤其是NSPredicate
),您可以简单地实现通配符匹配
func wildcard(_ string: String, pattern: String) -> Bool {
let pred = NSPredicate(format: "self LIKE %@", pattern)
return !NSArray(object: string).filtered(using: pred).isEmpty
}
LIKE比较完全符合您的要求:
左手表达式等于右手表达式:?和*允许用作通配符,其中?匹配1个字符,*匹配0个或更多字符。
示例:
print(wildcard("xyxzzxy", pattern: "x***y")) // true
print(wildcard("xyxzzxy", pattern: "x***x")) // false
print(wildcard("xyxzzxy", pattern: "x***x?")) // true
print(wildcard("xyxzzxy", pattern: "*")) // true
print(wildcard("a12b34c", pattern: "a?b?c")) // false
print(wildcard("a12b34c", pattern: "a*b*c")) // true
答案 1 :(得分:1)
如果问题是“ 设计高效算法 ...”,则可以通过以下方式在String上定义扩展名:
extension String {
func matches(wildcard pattern: String) -> Bool {
var strIndex = self.startIndex, matchIndex = self.startIndex
var patternIndex = pattern.startIndex, asteriskIndex = pattern.endIndex
while strIndex < self.endIndex {
//Characters match, or question mark
if patternIndex < pattern.endIndex
&& (self[strIndex] == pattern[patternIndex] || pattern[patternIndex] == "?") {
strIndex = self.index(after: strIndex)
patternIndex = pattern.index(after: patternIndex)
}
//Asterisk character
else if patternIndex < pattern.endIndex && pattern[patternIndex] == "*" {
asteriskIndex = patternIndex
matchIndex = strIndex
patternIndex = pattern.index(after: patternIndex)
}
else if asteriskIndex != pattern.endIndex {
patternIndex = pattern.index(after: asteriskIndex)
matchIndex = self.index(after: matchIndex)
strIndex = matchIndex
}
else { return false }
}
//Asterisk character at the end of the pattern
while patternIndex < pattern.endIndex && pattern[patternIndex] == "*" {
patternIndex = pattern.index(after: patternIndex)
}
return patternIndex == pattern.endIndex
}
}
这是this代码的可读性更高的版本。
以下是一些测试用例:
"xyxzzxy".matches(wildcard: "x***y") //true
"xyxzzxy".matches(wildcard: "x***x") //false
"xyxzzxy".matches(wildcard: "x***x?") //true
"xyxzzxy".matches(wildcard: "*") //true
答案 2 :(得分:0)
func matchingString() {
var savingValueOfJ = 0
var boolean = [Bool]()
inputString = inputStringTextField.text!
pattern = patternTextField.text!
let inputCharacters = Array(inputString)
let patternCharacters = Array(pattern)
for (index, firstCharacter) in patternCharacters.enumerated() {
if index == patternCharacters.count - 1, index != 0 {
if inputCharacters.last == firstCharacter || firstCharacter == "*" || firstCharacter == "?" {
boolean.append(true)
break
}
else {
boolean.append(false)
break
}
} else {
if firstCharacter != "*" {
while savingValueOfJ <= inputCharacters.count {
if firstCharacter == inputCharacters[savingValueOfJ] || firstCharacter == "?" {
boolean.append(true)
savingValueOfJ += 1
break
} else {
boolean.append(false)
savingValueOfJ += 1
break
}
}
}
}
}
let arr = boolean.filter{ $0 == false}
if arr.count > 0 {
displayingResultLbl.text = "Not A Match"
}
else {
displayingResultLbl.text = "Matche's"
}
}
答案 3 :(得分:0)
将Martin的解决方案更进一步,这是一个[String]
扩展名,它将接受模式并返回所有匹配的元素:
extension Array where Element == String {
func wildcard(pattern: String) -> [String] {
var returnArray: [String] = []
for item in self {
if (wildcard(item, pattern: pattern)) {
returnArray.append(item)
}
}
return returnArray
}
// Credit to Martin R @ SO for this brilliance: https://stackoverflow.com/a/57271935/215950
private func wildcard(_ string: String, pattern: String) -> Bool {
let pred = NSPredicate(format: "self LIKE %@", pattern)
return !NSArray(object: string).filtered(using: pred).isEmpty
}
}