【问题标题】:Swift: String firstIndex after characterSwift:字符后的字符串firstIndex
【发布时间】:2021-03-31 18:35:04
【问题描述】:

我正在尝试检测字符串上的括号,例如: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: ")"),你们中的任何人都知道怎么做吗?

【问题讨论】:

    标签: ios swift string substring xcode12


    【解决方案1】:

    更新了 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
    }
    

    【讨论】:

      【解决方案2】:

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

      要查找字符之后的第一个索引,您可以扩展集合并返回元素的 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)"
      

      【讨论】:

      • 我不想反转任何子字符串。我要做的是删除所有匹配括号
      • 如果在最后一个括号后面写了一些文字,那么它就不能正常工作。
      【解决方案3】:

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

      一种方法是“剪切”startIndex 处的字符串,然后得到下半部分。然后在子字符串上使用firstIndex(of:)。由于Substrings 只是对从中剪切它们的原始字符串的“视图”,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),它应该可以工作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-10-26
        • 1970-01-01
        • 1970-01-01
        • 2021-08-22
        • 2015-09-08
        • 1970-01-01
        • 2019-11-20
        相关资源
        最近更新 更多