【问题标题】:What’s the difference between Array<T>, ContiguousArray<T>, and ArraySlice<T> in Swift?Swift 中的 Array<T>、ContiguousArray<T> 和 ArraySlice<T> 有什么区别?
【发布时间】:2015-09-26 05:45:45
【问题描述】:

在 Swift 2 中,三种数组变体的主要区别是什么:

  • 数组
  • 连续数组
  • 数组切片

谁能用一个真实的例子来解释这个?

【问题讨论】:

标签: arrays swift slice


【解决方案1】:

Swift 定义了以下实现 ArrayType 协议的类; 数组、连续数组、切片

Swift Array 是表示数组的主类,数组是一个泛型类,接受 1 种类型,整数数组的类型为Array&lt;Int&gt;,创建一个整数数组:

var myArray = Array<Int>()

Slice 是一个具有内部实现的数组,它使得从数组顶部移除元素的计算成本很低。以下将在 Slice 类型上表现良好:

var arr = [1,2,3,4,5]
arr[1…4]

关于 ContiguousArray 的文档不多,但从它的名字可以猜到它与内部数组存储有关,可能元素存储在 Contiguous Memory Allocation 布局中。

Read more.

【讨论】:

    【解决方案2】:

    来自docs

    ContiguousArray:

    效率相当于Array,除非T是类或者@objc协议类型,这种情况下使用ContiguousArray可能效率更高。但是请注意,ContiguousArray 不会桥接到 Objective-C。有关更多详细信息,请参阅 Array,ContiguousArray 与其共享大多数属性。

    基本上,每当您将 classes@objc 协议 类型存储在数组中时,您可能需要考虑使用 ContiguousArray 而不是 Array

    数组切片

    ArraySlice 始终使用连续存储,并且不桥接到 Objective-C。

    警告:不鼓励长期存储 ArraySlice 实例

    因为 ArraySlice 呈现了一些更大的存储空间的视图 即使在原始数组的生命周期结束后,也存储切片 可能会延长不再可访问的元素的寿命, 这可以表现为明显的内存和对象泄漏。阻止 这个效果,ArraySlice 只用于瞬态计算。

    当您想从数组中获取子范围时,大多数情况下都会使用 ArraySlice,例如:

    let numbers = [1, 2, 3, 4]
    let slice = numbers[Range<Int>(start: 0, end: 2)] //[1, 2]
    

    您应该使用Array的任何其他情况。

    【讨论】:

      【解决方案3】:

      不同类 Swift 的良好来源是:http://swiftdoc.org/

      数组很清楚,接下来说说其他两个。

      连续数组:http://swiftdoc.org/type/ContiguousArray/

      一个快速、连续存储的 T 数组。

      效率等同于Array,除非T是一个类或者 @objc 协议类型,在这种情况下使用 ContiguousArray 可能更多 高效的。但是请注意, ContiguousArray 不会桥接到 目标-C。请参阅 Array,其中 ContiguousArray 共享最多 属性,了解更多详情。

      数组切片:http://swiftdoc.org/type/ArraySlice/

      表示任何 Array 的子序列的类 Array 类型, ContiguousArray 或其他 ArraySlice。

      ArraySlice 始终使用连续存储,并且不会桥接到 Objective-C。

      简而言之:

      ContiguousArray 是为了在 T 是类或 @objc 协议类型时提高效率 ArraySlice 是表示子部分中的 Array。

      【讨论】:

      • 我们可以将 ArraySlice 转换为 Array ,这可能与 Contiguous 数组一起使用。以及如何使用它以及何时使用?
      【解决方案4】:

      有来自 Apple 的新文档。 https://git.io/vg5uw

      所以,

      ContiguousArray&lt;Element&gt; 是三者中最快和最简单的——使用 当您需要“C 数组”性能时。一个元素 ContiguousArray 总是连续存储在内存中。

      .

      Array&lt;Element&gt; 类似于 ContiguousArray&lt;Element&gt;,但针对 从 Cocoa 和返回的高效转换——当 Element 可以是一个类时 类型,Array&lt;Element&gt; 可以由(可能不连续)支持 存储任意 NSArray 而不是 Swift 连续数组。 Array&lt;Element&gt; 还支持向上和向下转换 在相关类类型的数组之间。当 Element 已知为 非类类型,Array&lt;Element&gt; 的性能与之相同 ContiguousArray&lt;Element&gt;.

      【讨论】:

        【解决方案5】:

        切片维护指数

        这不是一个完整的答案。但是有一点来自 Swift 的哥特式风格:

        let array = [1,4,9,12,15]
        

        你认为下面的值会一样吗?

        print(array[2..<5].index(of:12)) // is it 1 or 3?
        print(array.index(of:12)) // 3
        

        是的!两者都会打印3。这是因为 ArraySlice 不会获得自己的唯一副本(除非 Array 发生了变异)。 ArraySlice 基本上是一种查看同一 Array 的某些索引的方法。它不会创建一个新的 [9,12,15] 数组并对其进行调查。它只会查看 original 数组的 给定范围

        现在怎么样?你认为下面的值会一样吗?

        print(array[2..<5].index(of:1)) // nil
        print(array.index(of:1)) // 0
        

        不! ArraySlice 将打印 nil,而 Array 将打印 0

        显然:

        print(array[2..<4][2]) // 9
        print(array[2..<4][0]) // ERROR: out of bounds
        

        又一次令人惊讶:

        print(array.dropFirst(2).index(of:15) 
        

        不是2。它将返回 4 作为其索引。为什么?因为dropFirst 返回一个ArraySlice。如果您不希望它维护索引,那么您应该从 ArraySlice 中构造一个新的 Array...

        编辑:

        来自docs

        与 Array 和 ContiguousArray 不同,ArraySlice 的起始索引 实例并不总是零。切片保持相同的索引 相同元素的更大数组,因此切片的起始索引 取决于它是如何创建的,让您执行基于索引的 对完整数组或切片进行操作。

        如果您有兴趣了解更多。文档的链接还有另一个示例

        【讨论】:

          猜你喜欢
          • 2012-03-10
          • 1970-01-01
          • 1970-01-01
          • 2021-04-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-09-01
          相关资源
          最近更新 更多