Swift的切片是什么?

What is a slice in Swift?

swift中的切片是什么?它与数组有什么不同?

从文档中,下标(范围)的类型签名为:

1
subscript(Range<Int>) -> Slice<T>

为什么不返回另一个Array,而不是一个Slice

看起来我可以将一个切片与一个数组连接起来:

1
2
var list = ["hello","world"]
var slice: Array<String> = [] + list[0..list.count]

但这会产生错误:

could not find an overload for 'subscript' that accepts the supplied
arguments

1
2
var list = ["hello","world"]
var slice: Array<String> = list[0..list.count]

什么是切片?


切片指向数组。当数组已经存在并且切片只能描述所需的部分时,不需要再创建另一个数组。

添加会导致隐式强制,因此它是有效的。要使您的任务生效,您需要强制:

1
2
var list = ["hello","world"]
var slice: Array<String> = Array(list[0..<list.count])


注意:对于Swift Beta 3,这个答案很高兴是无效的,因为数组现在是真值类型。

@Matt是正确的,上面-Slice指向数组。这似乎与Swift处理我们正在处理的所有其他数据类型的方式相反,因为这意味着切片的值可以更改,即使它声明为常量:

1
2
3
4
var arr = ["hello","world","goodbye"]    // ["hello","world","goodbye"]
let slice = arr[0..2]                      // ["hello","world"]
arr[0] ="bonjour"
println(slice)                             // ["bonjour","world"]

最糟糕的是,切片的行为就像一个数组。鉴于在Swift中,我们对不可变性有一个期望,因此切片的下标值可以在不发出警告的情况下更改似乎很危险:

1
2
3
println(slice[1])                          //"world"
arr[1] ="le monde"
println(slice[1])                          //"le monde"

但是,如果底层数组变化太大,它们将被取消挂钩:

1
2
3
4
arr.removeAtIndex(0)                       // this detaches slice from arr
println(slice)                             // ["bonjour","le monde"]
arr[0] ="hola"
println(slice)                             // ["bonjour","le monde"]


总结:

上面的答案直到测试版3都是正确的(在未来的版本中可能会再次改变)。

slice现在的作用就像一个数组,但是正如上面@matt所说,实际上是对引擎盖下的数组的一个很浅的复制,直到进行了更改。切片(现在)看到原始值的快照,

还要注意,slice语法已经更改:

1
[from..upToButNotIncluding] -> [from..<upToButNotIncluding]

例子:

1
2
3
4
5
6
7
var arr = ["hello","world","goodbye"] // ["hello","world","goodbye"]
var arrCopy = arr
let slice = arr[0..<2]                  // ["hello","world"]
arr[0] ="bonjour"
arr                                     // ["bonjour","world","goodbye"]
arrCopy                                 // ["hello","world","goodbye"]
slice                                   // ["hello","world"]

这允许更统一的处理,因为执行Python样式的列表处理(过滤一个列表以生成另一个列表)更简单(imho)。根据Matt在beta 3之前的回答,您必须创建一个临时数组来映射一个切片。新代码现在更简单了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class NameNumber {
    var name:String =""
    var number:Int = 0

    init (name:String, number:Int) {
        self.name = name
        self.number = number
    }
}

var number = 1
let names = ["Alan","Bob","Cory","David"]
let foo = names[0..<2].map { n in NameNumber(name:n, number:number++) }
foo     // [{name"Alan" number 1}, {name"Bob" number 2}]

(尽管公平地说,foo仍然是一块碎片)

参考文献:

http://adcdownload.apple.com//developer_tools/xcode_6_beta_3_lpw27r/xcode_6_beta_3_release_notes_uuuu.pdf

重要的变化,解决的问题,-SWIFT语言,第1段

"swift中的数组已经完全重新设计为具有像字典和字符串…