slice咱们这边把他翻译成 切片,咱们今天要看的就是关于 Array 切片的事情。比方说我们有一个数组。
var array = [1,2,3,4,5,6,7,8,9,10]
在这里我们就可以用Rangle类型的对象获得一个切片对象。
let slice = array[1...7] // [2,3,4,5,6,7,8]
在1...7的帮助下,我们获得了 [2,3,4,5,6,7,8] 这样一段切片,这个切片有几件很值得聊一聊的事情。
切片和数组array共享同一个indices
我们知道collection类型都一个 indices 属性,属于Range类型,对于数组来说 indices 属性就是 0,1,2,3..... 数组访问时使用的下标。slice与array共享同一个indices的方式,导致了 slice 很像一个 array 的视图。病症表现如下:
let firstItem = slice[0] // error !!!!!!
如果不特意区分的话,我们用1...7切下来的东西,简直就是一个array吗,但是它的下标值居然不是从 0 开始的。我们可以用 startIndex 确定一下它的下标起始位置。
slice.startIndex // 1
我们可以看到 slice 的下标是从1开始的,它和array共享的是同一个indices。
共享indices确不共享引用
如果slice是array的一个视图,那么他们共享同一个数组的引用其实是一个挺不错的好注意,但是吧,其实吧,事实并不是这样的。我们可以用一个例子证明一下
var arr1 = [1,2,3,4,5,6,7]
var slice1 = arr1[1...4]
arr1[1] = 10
slice1[1] // 2
我们改变了原素组中第二位置元素的值,但是,切片对应位置的值并没有一起变化。这是不是很好的体现了数组值类型的优良传统。
数组和切片作为参数时
切片常常处于计算的中间态,我们非常有可能需要把数组或切片作为参数进行传进以得到更进一步的处理。比方说,我们需要进行一起求和运算。我们定义如下一个方法。
func sum(array: Array<Int>) -> Int {
return array.reduce(0, combine: { (acc, i) in
return acc + i
})
}
let array: Array<Int> = [8, 9, 10]
let slice: ArraySlice<Int> = array[0...1]
sum(array) // 27
sum(slice) // Compiler error!
如果我们尝试进行这样的计算,那么在传递切片的时候,我们会遇到编译错误。因为切片的类型是ArraySlice,并不是Array类型。如果我们希望sum方法对切片也使用,那么我们必须对该方法做进一步的泛型化处理。在我们的sum方法中,主要是使用到 reduce 方法,其实只要实现了 sequenceType 协议就可以获得 reduce方法,值得庆幸的是 slice 与 array 都实现了 sequenceType 协议,因此,我们可以这样来处理一下。
func sum<T: SequenceType where T.Generator.Element == Int>(list: T) -> Int {
return list.reduce(0, combine: { (acc, e) in
return acc + e
})
}
我们将sum的参数泛型化,要求它是一个 SequenceType 类型,而且元素是 Int 类型。现在
sum(slice) // 17
好了,到这就结束了,我是 八条8tiao, 我真的不知道该怎么写总结,所以到目前为止,我没有写过总结。
网友评论