Что такое срез в Swift?

что такое срез в Swift и чем он отличается от массива?

из документации подпись типа индекса(диапазона):

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

почему бы не вернуть еще Array<T>, а не Slice<T>?

похоже, я могу объединить срез с массивом:

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

но это дает ошибку:

не удалось найти перегрузку для "индекса", который принимает поставляемый доводы

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

Что такое срез?

3 ответов


срез указывает на массив. Нет смысла делать другой массив, когда массив уже существует, и срез может просто описать желаемую его часть.

дополнительно вызывает неявное принуждение, поэтому оно работает. Чтобы ваше задание работало,вы нужно было бы принудить:

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

Примечание: этот ответ, К счастью, недействителен с 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"]

хуже всего то, что срез действует так же, как массив. Учитывая, что в Swift мы имеем ожидание неизменности кажется опасным, что подписанные значения среза могут меняться без предупреждения:

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

но если базовый массив изменяется слишком резко, они отцепляются:

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

резюме:

ответы выше были верны до бета-версии 3 (и могут снова измениться в будущих выпусках)

Slice теперь действует так же, как массив, но, как сказал @matt выше, фактически является мелкой копией массива под капотом, пока не будет сделано изменение. Фрагменты (теперь) см. снимок исходных значений,

также обратите внимание, что синтаксис среза изменился:

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

пример:

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

Это позволяет гораздо более равномерной обработки, как проще (IMHO) сделать обработку списка стилей python - фильтрацию одного списка, чтобы сделать другой. в ответе Мэтта до бета-версии 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}]

(хотя, честно говоря, Фу все еще кусочек)

ссылки:

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

Важные Изменения, Вопросы Решены, - Swift Language, Paragraph 1

"массив в Swift был полностью переработан, чтобы иметь полную семантику значения, такую как словарь и Строка...м"