我应该与remove(first :)一起使用哪个Swift字符计数?

时间:2018-08-23 18:40:58

标签: swift string

在String上有一个removeFirst(_:)方法。但是,该文档似乎非常通用,并且没有提及有关特定于字符串的任何内容:

  

k :要从集合中删除的元素数。 k必须大于或等于零,并且不得超过集合中的元素数量。

var bugs = ["Aphid", "Bumblebee", "Cicada", "Damselfly", "Earwig"]
bugs.removeFirst(3)
print(bugs)
// Prints "["Damselfly", "Earwig"]"

实际上,它看起来与removeFirst(_ :)的ArrayCollection文档非常相似。

由于至少需要6 different ways才能在Swift中获取字符数,所以很难知道我应该为k使用哪个字符数。

如果我想创建诸如string.removePrefix("foo")之类的方法,应该使用6个字符计数中的哪个?

2 个答案:

答案 0 :(得分:5)

removeFirst(_:)RangeReplaceableCollection协议的方法,对于任何集合,count 给出其元素的数量。因此,对于a类型的任何实例RangeReplaceableCollection, 自变量k传递给

a.removeFirst(k)

必须大于或等于零,并且小于或等于a.count

这适用于ArrayString(是Character的集合) 以及所有其他“范围可替换的集合”类型:

// Array:
var arr = [1, 2, 3, 4]
arr.removeFirst(k)   // 0 <= k <= arr.count

// String:
var str = "‍‍‍"
str.removeFirst(k)   // 0 <= k <= str.count

// Unicode scalar view of a string:
var u = "‍‍‍".unicodeScalars
u.removeFirst(k)   // 0 <= k <= u.count

话虽如此,我将实现为

extension String {
    func removingPrefix(_ prefix: String) -> String? {
        guard let range = range(of: prefix, options: .anchored) else {
            return nil
        }
        return String(self[range.upperBound...])
    }
}

避免不必要的索引/偏移量转换。

答案 1 :(得分:0)

似乎希望您使用string.count

游乐场测试:

func test(_ string: String, _ desc: String? = nil) {
  var s = string
  s.removeFirst(1)
  print("\(string) -> \(s)")
  assert(string.count == s.count + 1)
}

test("abc")
test("❌")
test("")
test("☾test")
test("‍‍‍")
test("\u{200d}\u{200d}\u{200d}")
test("")
test("\u{1F468}")
test("‍♀️‍♂️")
test("你好吗")
test("مرحبا", "Arabic word")
test("م", "Arabic letter")
test("שלום", "Hebrew word")
test("ם", "Hebrew letter")

输出:

abc -> bc
❌ -> 
 -> 
☾test -> test
‍‍‍ -> 
‍‍‍ -> 
 -> 
 -> 
‍♀️‍♂️ -> ‍♀️‍♂️
你好吗 -> 好吗
مرحبا -> رحبا
م -> 
שלום -> לום
ם -> 

因此您可以创建:

extension String {

  /// Removes a prefix from a string, if it exists.
  ///
  /// - Parameter prefix: The prefix to attempt to remove.
  /// - Returns: The string without the prefix, or `nil` if the prefix didn't exist.
  func removingPrefix(_ prefix: String) -> String? {
    guard starts(with: prefix) else {
      return nil
    }

    var result = self
    result.removeFirst(prefix.count)
    return result
  }
}

请参见Martin's answer,以实现更好的实现