通配符模式匹配:

时间:2019-07-30 10:47:14

标签: swift xcode

通配符模式匹配:给定一个字符串和一个包含通配符的模式,即*?,其中?可以匹配输入字符串中的任何单个字符,而{{1} }可以匹配任意数量的字符(包括零个字符),设计一种有效的算法来查找模式是否与完整的输入字符串匹配。

例如:

  • 输入:字符串=“ xyxzzxy”,样式=“ x *** y”

    输出:匹配

  • 输入:字符串=“ xyxzzxy”,样式=“ x *** x”

    输出:无匹配项

  • 输入:字符串=“ xyxzzxy”,模式=“ x *** x?”

    输出:匹配

  • 输入:字符串=“ xyxzzxy”,样式=“ *”

    输出:匹配

4 个答案:

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