Swift中的Array、ContiguousArray和ArraySlice有什么< T>< T>区别< T>?

vfh0ocws  于 2023-08-02  发布在  Swift
关注(0)|答案(6)|浏览(154)

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

  • 阵列
  • 连续数组
  • 阵列切片

有人能用一个真实的世界的例子来解释这一点吗?

j2qf4p5b

j2qf4p5b1#

关于docs

ContiguousArray:

效率等同于Array,除非T是class或@objc协议类型,在这种情况下使用ContiguousArray可能更有效。但是,请注意,ContiguousArray并不桥接到Objective-C。有关更多详细信息,请参见Array,ContiguousArray与Array共享大多数属性。
基本上,每当你在数组中存储classes或**@objc protocol**类型时,你可能需要考虑使用ContiguousArray而不是Array

数组切片

ArraySlice始终使用连续存储,并且不会桥接到Objective-C。
警告:不建议长期存储ArraySlice示例
因为即使在原始阵列的生命周期结束之后,ArraySlice也会呈现对某个较大阵列的存储的视图,所以存储切片可能会延长不再可访问的元素的生命周期,这可能表现为明显的内存和对象泄漏。为了防止这种影响,请仅将ArraySlice用于 transient 计算。
ArraySlice在大多数情况下用于从Array中获取子范围,例如:

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

字符串
在其他情况下,您应该使用Array

yzxexxkh

yzxexxkh2#

关于Swift不同类的好源代码是:http://swiftdoc.org/
数组非常清楚,所以我们来谈谈另外两个。
连续阵列:http://swiftdoc.org/type/ContiguousArray/
一种快速连续存储的T.
效率等同于Array,除非T是class或@objc协议类型,在这种情况下使用ContiguousArray可能更有效。但是,请注意,ContiguousArray并不桥接到Objective-C。有关更多详细信息,请参见Array,ContiguousArray与Array共享大多数属性。
ArraySlice:http://swiftdoc.org/type/ArraySlice/
类数组类型,表示任意Array、ContiguousArray或其他ArraySlice的子序列。
ArraySlice始终使用连续存储,并且不会桥接到Objective-C。
简而言之:
当T是类或@objc协议类型时,ContiguousArray是为了更高的效率,ArraySlice将在子部分中表示Array。

wdebmtf2

wdebmtf23#

苹果的新文档。https://git.io/vg5uw
所以
ContiguousArray<Element>是这三种方法中最快、最简单的一种,当你需要“C数组”性能时,就可以使用它。ContiguousArray的元素始终连续存储在内存中。
.
Array<Element>类似于ContiguousArray<Element>,但优化了从可可和back的高效转换-当Element可以是类类型时,Array<Element>可以由任意NSArray的(可能不连续的)存储支持,而不是Swift ContiguousArray。Array<Element>还支持相关类类型数组之间的向上和向下转换。当已知Element是非类类型时,Array<Element>的性能与ContiguousArray<Element>的性能相同。

r8uurelv

r8uurelv4#

Swift定义了以下实现ArrayType协议的类;Array、ContiguousArray、Slice
Swift Array是表示数组的主类,数组是一个泛型类,它采用1类型,整数数组的类型为Array<Int>,创建一个整数数组:

var myArray = Array<Int>()

字符串
Slice是一个内部实现的数组,使得从数组顶部移除元素在计算上便宜。以下内容将在切片类型上执行良好:

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


关于ContiguousArray的文档不多,但从它的名字可以猜到它与内部阵列存储有关,可能元素存储在ContiguousArray布局中。
Read more.

dddzy1tm

dddzy1tm5#

切片维护索引

这不是一个完整的答案。但有一点来自Swift的gothcha:

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]并查看它。它只会查看原始数组的给定范围。
现在这个怎么样?您认为以下的值是否相同?

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。
编辑:

docs
与Array和ContiguousArray不同,ArraySlice示例的起始索引并不总是零。切片为相同元素维护较大数组的相同索引,因此切片的起始索引取决于它的创建方式,允许您对完整数组或切片执行基于索引的操作。
如果你有兴趣的话。文档的链接还有另一个例子

f8rj6qna

f8rj6qna6#

这里发生的事情是,Swift设计师正在创建一些并不真正有用的东西。ArraySlice范例使得在没有“起始”索引的情况下跨一个编码的字符串值并提取单个片段变得非常困难,因此您最终会得到代码,在传递一个切片的函数中,必须创建自己的索引值,从切片的起始索引开始,然后用习惯于其他语言的人不熟悉的表达式和概念在切片中前进,其他数组或集合数据结构。
解析一个字符串并从中提取字符,并计算字符的ascii数值变得非常困难。

相关问题