什么是Swift片?

hji*_*ing 85 slice swift

什么是Swift中的切片,它与数组有何不同?

从文档中,下标(Range)的类型签名是:

subscript(Range<Int>) -> Slice<T>
Run Code Online (Sandbox Code Playgroud)

为什么不返回另一个Array<T>而不是一个Slice<T>

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

var list = ["hello", "world"]
var slice: Array<String> = [] + list[0..list.count]
Run Code Online (Sandbox Code Playgroud)

但这会产生错误:

找不到接受提供的参数的'下标'的重载

var list = ["hello", "world"]
var slice: Array<String> = list[0..list.count]
Run Code Online (Sandbox Code Playgroud)

什么是切片?

mat*_*att 96

切片指向数组.当数组已经存在且切片只能描述它的所需部分时,没有必要创建另一个数组.

这种加法导致了隐含的强制,所以它有效.要使您的作业有效,需要强制:

var list = ["hello", "world"]
var slice: Array<String> = Array(list[0..<list.count])
Run Code Online (Sandbox Code Playgroud)

  • 如果您添加了一个简单的编辑通知新读者范围运算符已更改,它不会破坏通信吗? (7认同)
  • 快速语言已经改变,切片实际上使用三个省略号而不是两个https://developer.apple.com/library/ios/documentation/General/Reference/SwiftStandardLibraryReference/Array.html (4认同)
  • 这真的是一个实现细节.你巧妙地探查了揭示黑匣子运作的边缘情况......! (2认同)
  • 实际上Slice是数组的副本.更新原始数组后,切片不会更改.这是因为结构性质.对于注释,Sliceable协议并不意味着使用Slice类型 (2认同)

Nat*_*ook 22

注意:从Swift beta 3开始,这个答案很快就失效了,因为数组现在是真正的值类型.


@matt是正确的,上面 - Slice<T>数组中的点.这似乎与Swift处理我们正在使用的所有其他数据类型的方式相反,因为这意味着即使将片声明为常量,切片的值也会发生变化:

var arr = ["hello", "world", "goodbye"]    // ["hello", "world", "goodbye"]
let slice = arr[0..2]                      // ["hello", "world"]
arr[0] = "bonjour"
println(slice)                             // ["bonjour", "world"]
Run Code Online (Sandbox Code Playgroud)

最糟糕的是,切片就像一个数组.鉴于在Swift中我们对不可变性有所期待,切片的下标值可能会在没有警告的情况下发生变化,这似乎是危险的:

println(slice[1])                          // "world"
arr[1] = "le monde"
println(slice[1])                          // "le monde"
Run Code Online (Sandbox Code Playgroud)

但是如果底层数组变化太大,它们就会脱钩:

arr.removeAtIndex(0)                       // this detaches slice from arr
println(slice)                             // ["bonjour", "le monde"]
arr[0] = "hola"
println(slice)                             // ["bonjour", "le monde"]
Run Code Online (Sandbox Code Playgroud)

  • 事实上,正如你所说,切片只是像数组一样工作.Swift数组具有可变元素*,即使它们被声明为不可变*.例如,尝试`let arr = ["hello","world","goodbye"]; arr [0] ="bonjour"`.你会发现它有效.奇怪的是,对于不可变数组,只有*size*是不可变的,而不是内容.(参见*Swift编程语言中的"集合的可变性"*) (6认同)

Chr*_*ver 14

摘要:

以上答案在Beta 3之前都是正确的(并且可能在将来的版本中再次更改)

Slice现在就像一个数组一样,但正如上面所说的@matt,实际上是一个浅层复制到引擎盖下的数组,直到做出改变.切片(现在)查看原始值的快照,

另请注意,切片语法已更改:

[from..upToButNotIncluding] -> [from..<upToButNotIncluding]
Run Code Online (Sandbox Code Playgroud)

例:

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"]
Run Code Online (Sandbox Code Playgroud)

这允许更加统一的处理,因为更简单(恕我直言)进行python样式列表处理 - 过滤一个列表来制作另一个列表.根据Matt在Beta 3之前的答案,您必须创建一个临时数组才能映射切片.新代码现在更简单:

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}]
Run Code Online (Sandbox Code Playgroud)

(虽然公平地说,foo仍然是一片)

参考:

http://adcdownload.apple.com//Developer_Tools/xcode_6_beta_3_lpw27r/xcode_6_beta_3_release_notes__.pdf

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

"Swift中的数组已经完全重新设计,具有完整的语义,如Dictionary和String ...... m"