¿Qué es un slice en Swift?


¿Qué es un slice en Swift y en qué se diferencia de un array?

De la documentación, la firma de tipo de subíndice (Rango) es:

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

¿Por qué no devolver otro Array<T> en lugar de un Slice<T>?

Parece que puedo concatenar una rebanada con una matriz:

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

Pero esto produce el error:

No se pudo encontrar una sobrecarga para 'subíndice' que acepte el argumentos

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

¿Qué es una rebanada?

 86
Author: matt, 2014-06-06

3 answers

El corte apunta a la matriz. No tiene sentido hacer otro array cuando el array ya existe y el slice solo puede describir la parte deseada del mismo.

La adición causa coerción implícita, por lo que funciona. Para hacer que su tarea funcione, usted tendría que coaccionar:

var list = ["hello", "world"]
var slice: Array<String> = Array(list[0..<list.count])
 95
Author: matt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-06 13:12:27

Nota: Esta respuesta es felizmente inválida a partir de Swift beta 3, ya que los arrays ahora son tipos de valor verdaderos.


@ matt es correcto, arriba - el Slice<T> apunta al array. Eso parece contrario a la forma en que Swift maneja todos los otros tipos de datos con los que estamos trabajando, ya que significa que el valor del segmento puede cambiar incluso si se declara como una constante:

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

La peor parte es que el slice actúa como un array. Dado que en Swift tenemos una expectativa de inmutabilidad parece peligroso que los valores subscriptos del slice puedan cambiar sin previo aviso:

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

Pero si la matriz subyacente cambia demasiado drásticamente, se desenganchan:

arr.removeAtIndex(0)                       // this detaches slice from arr
println(slice)                             // ["bonjour", "le monde"]
arr[0] = "hola"
println(slice)                             // ["bonjour", "le monde"]
 21
Author: Nate Cook,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-10 02:40:44

Resumen:

Las respuestas anteriores fueron ciertas hasta la Beta 3 (y pueden cambiar de nuevo en futuras versiones)

Slice ahora actúa como una matriz, pero como @matt dijo anteriormente, es efectivamente una copia superficial de una matriz bajo el capó, hasta que se realiza un cambio. Slices (ahora) ver una instantánea de los valores originales,

También tenga en cuenta que la sintaxis de slice ha cambiado:

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

Ejemplo:

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"]

Esto permite un procesamiento mucho más uniforme, ya que es más simple (en mi humilde opinión) hacer python style list processing-filtrar una lista para hacer otra. según la respuesta de Matt antes de la Beta 3, tenías que crear una matriz temporal para mapear un segmento. El nuevo código es ahora más simple:

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}]

(aunque para ser justos, foo sigue siendo una rebanada)

Referencia:

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

Cambios Importantes, Problemas Resueltos, - Swift Language, Párrafo 1

" Matriz en Swift ha sido completamente rediseñado para tener semántica de valor completo como Diccionario y Cadena...m "

 14
Author: Chris Conover,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-08 17:29:55