繁体   English   中英

Swift:字符串 firstIndex 在字符之后

[英]Swift: String firstIndex after character

我正在尝试检测字符串上的括号,例如: foo(bar)baz(blim)并反转括号内的内容,但我的实现超出了反弹范围:

func reverseInParentheses(inputString: String) -> String {
    var tmpStr = inputString
    var done = false
    while !done {
        if let lastIndexOfChar = tmpStr.lastIndex(of: "(") {
            let startIndex = tmpStr.index(lastIndexOfChar, offsetBy:1)
            if let index = tmpStr.firstIndex(of: ")") {
                let range = startIndex..<index
                let strToVerse = String(tmpStr[range])
                let reversedStr = reverseStr(str: strToVerse)
                tmpStr = tmpStr.replacingOccurrences(of: "(" + strToVerse + ")", with: reversedStr)
                
            }
        } else {
            done = true
        }
    }
    return tmpStr
}

我怎样才能在startIndex之后获得tmpStr.firstIndex(of: ")")你们中的任何人都知道如何做到这一点?

如何在startIndex之后获得tmpStr.firstIndex(of: ")")

一种方法是在startIndex处“剪切”字符串,并获得下半部分。 然后在 substring 上使用firstIndex(of:) 由于Substring只是原始字符串的“视图”,因此firstIndexOf仍然返回原始字符串的索引。

let string = "foo(bar)baz(blim)"
if let lastIndexOfChar = string.lastIndex(of: "(") {
    let startIndex = string.index(after: lastIndexOfChar)
    let substring = string[startIndex..<string.endIndex] // cut off the first part of the string.
    // now you have a "Substring" object
    if let indexAfterOpenBracket = substring.firstIndex(of: ")") {
        // prints "blim", showing that the index is indeed from the original string
        print(string[startIndex..<indexAfterOpenBracket])
    }
}

您可以将其编写为扩展:

extension StringProtocol {
    func firstIndex(of char: Character, after index: Index) -> Index? {
        let substring = self[index..<endIndex]
        return substring.firstIndex(of: char)
    }
}

现在,如果您在reverseInParentheses中调用tmpStr.firstIndex(of: ")", after: startIndex) ,它应该可以工作。

您可以迭代保留索引作为参考的字符串,以将其与 endIndex 进行比较。 因此,每次您成功找到一个范围时,您都会在结束索引之后开始进行新的搜索。 顺便说一句,您不应该使用 replaceOccurrences,因为它也可能替换不在括号内的单词。 您可以使用 RangeReplaceableCollection replaceSubrange并将反转的 substring 传递给该方法。

要查找字符之后的第一个索引,您可以扩展集合并返回元素的 firstIndex 之后的索引(如果找到):

extension Collection where Element: Equatable {
    func firstIndex(after element: Element) -> Index? {
        guard let index = firstIndex(of: element) else { return nil }
        return self.index(after: index)
    }
}

您的方法应如下所示:

func reverseInParentheses(inputString: String) -> String {
    var inputString = inputString
    var startIndex = inputString.startIndex
    while startIndex < inputString.endIndex,
        let start = inputString[startIndex...].firstIndex(after: "("),
        let end = inputString[start...].firstIndex(of: ")") {
        inputString.replaceSubrange(start..<end, with: inputString[start..<end].reversed())
        startIndex = inputString.index(after: end)
    }
    return inputString
}

let str = "foo(bar)baz(blim)"
reverseInParentheses(inputString: str)  // "foo(rab)baz(milb)"


或扩展StringProtocol并将Self约束到RangeReplaceableCollection

extension StringProtocol where Self: RangeReplaceableCollection {
    var reversingSubstringsBetweenParentheses: Self {
        var startIndex = self.startIndex
        var source = self
        while startIndex < endIndex,
            let start = source[startIndex...].firstIndex(after: "("),
            let end = source[start...].firstIndex(of: ")") {
            source.replaceSubrange(start..<end, with: source[start..<end].reversed())
            startIndex = index(after: end)
        }
        return source
    }
}

let str = "foo(bar)baz(blim)"
str.reversingSubstringsBetweenParentheses  // "foo(rab)baz(milb)"

更新了 Leo Dabus 的答案,以防在最后一个括号后写更多的文字。

func reverseInParentheses(_ str: String) -> String {
    var str = str
    var startIndex = str.startIndex
    Var lastIndexOfChar = str.lastIndex(of: ")") ?? startIndex
    while startIndex < lastIndexOfChar {
        let start = str[startIndex...].firstIndex(after: "("),
        let end = str[start...].firstIndex(of: ")") {
        str.replaceSubrange(start..<end, with: str[start..<end].reversed())
        startIndex = str.index(after: end)
    }
    return str
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM