What have I done so far?

  1. 我在公共documentation中寻找初始值设定项.

  2. 我看了看open source code,见下面的代码.

Detail

在看了方法定义之后,我认为我们可以进一步澄清这个问题,即Sequence/Array将以连续的字节存储,而UTF8将被使用.


  /// Creates a string from the given Unicode code units in the specified
  /// encoding.
  ///
  /// - Parameters:
  ///   - codeUnits: A collection of code units encoded in the encoding
  ///     specified in `sourceEncoding`.
  ///   - sourceEncoding: The encoding in which `codeUnits` should be
  ///     interpreted.
  @inlinable
  @inline(__always) // Eliminate dynamic type check when possible
  public init<C: Collection, Encoding: Unicode.Encoding>(
    decoding codeUnits: C, as sourceEncoding: Encoding.Type
  ) where C.Iterator.Element == Encoding.CodeUnit {
    guard _fastPath(sourceEncoding == UTF8.self) else {
      self = String._fromCodeUnits(
        codeUnits, encoding: sourceEncoding, repair: true)!.0
      return
    }

    // Fast path for user-defined Collections and typed contiguous collections.
    //
    // Note: this comes first, as the optimizer nearly always has insight into
    // wCSIA, but cannot prove that a type does not have conformance to
    // _HasContiguousBytes.
    if let str = codeUnits.withContiguousStorageIfAvailable({
      (buffer: UnsafeBufferPointer<C.Element>) -> String in
      Builtin.onFastPath() // encourage SIL Optimizer to inline this closure :-(
      let rawBufPtr = UnsafeRawBufferPointer(buffer)
      return String._fromUTF8Repairing(
        UnsafeBufferPointer(
          start: rawBufPtr.baseAddress?.assumingMemoryBound(to: UInt8.self),
          count: rawBufPtr.count)).0
    }) {
      self = str
      return
    }

    // Fast path for untyped raw storage and known stdlib types
    if let contigBytes = codeUnits as? _HasContiguousBytes,
      contigBytes._providesContiguousBytesNoCopy
    {
      self = contigBytes.withUnsafeBytes { rawBufPtr in
        Builtin.onFastPath() // encourage SIL Optimizer to inline this closure
        return String._fromUTF8Repairing(
          UnsafeBufferPointer(
            start: rawBufPtr.baseAddress?.assumingMemoryBound(to: UInt8.self),
            count: rawBufPtr.count)).0
      }
      return
    }

    self = String._fromNonContiguousUnsafeBitcastUTF8Repairing(codeUnits).0
  }

推荐答案

这不是对时间复杂性的formal分析,但希望足够具体以满足您的需求:从代码单元集合创建字符串的时间复杂性是O(n)(其中n是以代码单元为单位的输入集合的长度).

来自Collection个代码单元的String初始化具有三条初始化路径:

  1. String._fromCodeUnits(_:encoding:repair:)用于非UTF-8输入
  2. String._fromUTF8Repairing(_:)用于连续的UTF-8输入(例如,现有字符串或UTF-8代码单元的Array)
  3. String._fromNonContiguousUnsafeBitcastUTF8Repairing(_:),它将输入集合转换为Array,然后对结果数组调用String._fromUTF8Repairing(_:)(2
    • 这个副本本身是O(n),因为输入集合中的每个代码单元都被复制到数组中(每个代码单元的恒定时间)

所以我们有两个 case 要看:

  1. String._fromCodeUnits(_:encoding:repair:) itself has two main paths:
    • 如果输入为非ASCII,则每个代码单元将被迭代并将transcoded转换为UTF-8;从可能的输入编码进行代码转换是一个恒定的时间操作(所有支持的编码都有以字节为单位的代码单元长度的固定上限,因此对操作的复杂性有一个固定的恒定上限),因此这里的整体操作是O(n)次构造
    • 如果输入是ASCII,则迭代每个代码单元并将其验证为ASCII,然后按原样复制(因为ASCII是UTF-8的子集);因 for each 代码单元是在固定时间复制的,所以这里的总运算量为O(n)
  2. String._fromUTF8Repairing(_:) validates all of the code units in the input collection to ensure they're all valid UTF-8
    • 如果全部有效,则整个集合为copied as-is(每个代码单元在恒定时间内),因此为O(n)
    • 如果任何代码单元无效,则通过复制有效的UTF-8代码单元的范围,并用Unicode替换字符替换无效的UTF-8代码单元的范围,字符串为repaired.每个代码单元只需要被访问一次,如果有效则被复制,或者如果无效则跳过,这是在恒定时间内完成的,这使得操作在O(n)

就这样.

  1. ASCII输入:O(n)(验证)+O(n)(副本)=O(n)
  2. 非ASCII、非UTF-8输入:O(n)(转码+复制)
  3. 连续的UTF-8输入:O(n)(验证)+O(n)(修复/复制)=O(n)
  4. 非连续UTF-8输入:O(n)(复制到数组中)+O(n)(连续运算(3))=O(n)

或者,也许更直观的是:

  • 复制字符串时,需要一次访问一个代码单元以复制它
  • 复制单个代码单元是一个恒定的时间操作(因为代码单元的字节长度有一个固定的上限)
    • 如果您 Select 用不同的代码单元替换代码单元,您可以在固定时间内做出决定(复制that个字符只是固定时间)

O(n [length] * 1 [copy or replace]) = O(n)

Swift相关问答推荐

为什么Swift在某些链调用中不能对不可变值使用变异成员,而在其他链调用中则不能使用变异成员?

在Swift中,是否只有iOS版本超过15才能导入Swift包?

OBJC代码中Swift 演员的伊瓦尔:原子还是非原子?

格式化单位和度量值.为什么从符号初始化的单位不能产生与静态初始化相同的结果

SWIFT闭包使用的是陈旧的值,即使它是S@转义

我在SwiftUI中的动画无法正常工作

为SwiftUI文本视图提供固定宽度,并仅在文本换行时使文本视图底部增大

如何使泡泡上的箭头直达封闭矩形

SwiftUI 组合问题:通过 AppEventsManager 在 ViewModel 之间共享数据

PassthroughSubject 的 AsyncPublisher 值属性未生成所有值

我如何读取并通知可可 macos 中某个类的计算(computed)属性?

在 Swift 的异步上下文中,如何指示我想要函数的同步版本?

当使用 CGFloat 而不是数字文字时,为什么 node 的位置会发生变化?

引用类型(类)不需要但 struct 需要的可识别 id

如何删除标签和步进按钮之间的间距是 SwiftUI Stepper?

异步等待不会在项目中触发,但在 Xcode playground 中工作正常

如何在 SwiftUI 中以编程方式滚动列表?

不能从非开放类继承 swift

Swift if 语句 - 多个条件用逗号分隔?

UISearchbar TextField 的高度可以修改吗?