Что такое срез в 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}]
(хотя, честно говоря, Фу все еще кусочек)
ссылки:
Важные Изменения, Вопросы, Разрешаемые, - Swift Язык, Пункт 1
"массив в Swift был полностью переработан, чтобы иметь полную семантику значений, таких как словарь и Строка...м"