【问题标题】:Swift version of Objective C rstrip: index problemsObjective C rstrip 的 Swift 版本:索引问题
【发布时间】:2015-12-18 04:47:42
【问题描述】:

我正在尝试重写this Objective C method,它具有与 Python 的lstrip(从字符串的左侧删除字符)和rstrip(去除字符串的右侧)类似的功能。

lstrip 版本效果很好:

// this works
func lstrip(st_in: String,
            trimSet: NSCharacterSet=NSCharacterSet.whitespaceAndNewlineCharacterSet())-> String {
    let wanted=trimSet.invertedSet
    if let r=st_in.rangeOfCharacterFromSet(wanted) {
        return st_in.substringFromIndex(r.startIndex)
    }
    return ""
}

我在使用rstrip 版本时遇到了问题。

这就是我所拥有的:

// does not compile
func rstrip(st_in: String,
    trimSet: NSCharacterSet=NSCharacterSet.whitespaceAndNewlineCharacterSet())-> String {
        let wanted=trimSet.invertedSet
        let tgt=String(st_in.characters.reverse())
        if let r=tgt.rangeOfCharacterFromSet(wanted) {
            // st_in.characters.count - r.startIndex
            return st_in.substringToIndex(st_in.startIndex.advancedBy((st_in.characters.count as Int) - (r.startIndex as Int)))
        }
        return ""
}

问题:

  1. .rangeOfCharacterFromSet 的 Swift 版本似乎不支持 options:NSBackwardsSearch -- 我在 st_in.characters.reverse() 上使用前向搜索,这似乎可以工作;
  2. 主要问题(我的问题是)st_in.substringToIndex(st_in.startIndex.advancedBy((st_in.characters.count as Int) - (r.startIndex as Int))) 无法编译。我可以在调试器中看到这些值是正确的,但是r.startIndexIndex 类型,我不能直接将该值用于算术,也不能将其强制为 Int 值,也不能访问我在其中看到的价值。

所以在调试器中给出这个:

56> st 
$R33: String = "  \t\n  I needz trimin'¡    \t\n\n\n\n"
 57> String(st.characters.reverse()) 
$R34: String = "\n\n\n\n\t    ¡'nimirt zdeen I  \n\t  "
 58> String(st.characters.reverse()).rangeOfCharacterFromSet(trimSet.invertedSet)!.startIndex 
$R35: Index = {
  _base = {
    _position = 9
    _core = {
      _baseAddress = 0x0000000101207ee0
      _countAndFlags = 9223372036854775839
      _owner = Some {
        instance_type = 0x0000000101207ec0
      }
    }
  }
  _lengthUTF16 = 1
}

您可以在 Index 结构中看到 _position=9 —— 这正是我在 st_in.substringToIndex(st_in.startIndex.advancedBy(st_in.characters.count - r.startIndex)) 中所需要的,但我不知道如何在 Swift 中访问它。

想法?

【问题讨论】:

    标签: objective-c string swift swift2


    【解决方案1】:

    rangeOfCharacterFromSet() 确实支持从源字符串的末尾开始搜索,但是 Objective-C 的 NSBackwardsSearch 被导入到 斯威夫特.BackwardsSearch:

    func rstrip(st_in: String,
        trimSet: NSCharacterSet = NSCharacterSet.whitespaceAndNewlineCharacterSet())-> String {
            let wanted = trimSet.invertedSet
            if let r = st_in.rangeOfCharacterFromSet(wanted, options: .BackwardsSearch) {
                return st_in.substringToIndex(r.endIndex)
            }
            return ""
    }
    

    例子:

    let s1 = " foo bar      "
    let s2 = rstrip(s1)
    
    print(">\(s1)<")
    print(">\(s2)<")
    
    // Output:
    // > foo bar      <
    // > foo bar<
    

    所以你不需要对反转的字符串进行操作。 但无论如何要回答你的问题:这就是它的工作原理:

    func rstrip(st_in: String,
        trimSet: NSCharacterSet=NSCharacterSet.whitespaceAndNewlineCharacterSet())-> String {
            let wanted = trimSet.invertedSet
            let tgt = String(st_in.characters.reverse())
            if let r = tgt.rangeOfCharacterFromSet(wanted) {
                let length = tgt.startIndex.distanceTo(r.startIndex)
                return st_in.substringToIndex(st_in.endIndex.advancedBy(-length))
            }
            return ""
    }
    

    而不是 castingInt 的字符串索引(不会编译), distanceTo() 用于计算长度为Distance (对于String.CharacterView,恰好是Int), 和 that 可以用于算术,例如-length.

    【讨论】:

      【解决方案2】:

      我使用了一些不同的方法。 (我尝试使用“纯 Swift”并尽可能避免导入 Foundation。也许我用 Swift3.0 改变了主意)

      extension String {
          var rtrim: String {
              var s = self.characters
              while s.last == " " { s = s.dropLast() }
              return String(s)
          }
          var ltrim: String {
              var s = self.characters
              while s.first == " " { s = s.dropFirst() }
              return String(s)
          }
          var trim:String {
              return self.ltrim.rtrim
          }
      }
      
      let str = "\nalfa\nbeta\nga ma\n   delta   \n\na"
      let c = str.characters
      let trimmedLines = c.split("\n", allowEmptySlices: false).map{ String($0).trim }
      print(str.debugDescription, trimmedLines)
      
      // "\nalfa\nbeta\nga ma\n   delta   \n\na" ["alfa", "beta", "ga ma", "delta", "a"]
      

      【讨论】:

        猜你喜欢
        • 2014-08-07
        • 1970-01-01
        • 1970-01-01
        • 2016-03-22
        • 2015-11-03
        • 1970-01-01
        • 1970-01-01
        • 2023-03-23
        • 1970-01-01
        相关资源
        最近更新 更多