Swift'de dilim nedir?


85

Swift'de dilim nedir ve diziden farkı nedir?

Belgelerden, alt simge (Aralık) tür imzası şöyledir:

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

Neden Array<T>a yerine başka bir tane döndürmüyorsunuz Slice<T>?

Görünüşe göre bir dilimi bir dizi ile birleştirebilirim:

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

Ancak bu hata verir:

sağlanan bağımsız değişkenleri kabul eden 'alt simge' için bir aşırı yükleme bulamadı

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

Dilim nedir?

Yanıtlar:


97

Dilim, diziye işaret eder. Dizi zaten mevcutken ve dilim sadece istenen kısmını tanımlayabildiğinde başka bir dizi oluşturmanın anlamı yok.

Ekleme örtük zorlamaya neden olur, bu nedenle işe yarar. Görevinizin işe yaraması için şunları zorlamanız gerekir:

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

Mantıklı. Bu, belgelerin herhangi bir yerinde açıklanıyor mu?
2014

2
Bu bir uygulama detayı, gerçekten. Kara kutunun işleyişini ortaya çıkaran uç durumu akıllıca incelediniz ...!
mat

2
aslında Slice, dizinin kopyasıdır. Orijinal diziyi güncelledikten sonra, dilim değişmeyecek. Bunun nedeni yapı doğasıdır. Ve not için, Dilimlenebilir protokol, Dilim türünün kullanımı anlamına gelmez
Marcin

4
Hızlı dil değişti ve bir dilim aslında üç elips kullanıyor, iki geliştirici
Apple.com/library/ios/documentation/General/Reference/…

7
Yeni okuyuculara aralık operatörlerinin değiştiğini bildiren basit bir düzenleme eklerseniz, yazışmaları mahvetmez miydiniz?
Daniel Galasko

22

Not: Diziler artık gerçek değer türleri olduğundan, bu yanıt Swift beta 3'ten itibaren mutlu bir şekilde geçersizdir.


@matt doğru, yukarıda - Slice<T>diziye giren noktalar. Bu, Swift'in birlikte çalıştığımız diğer tüm veri türlerini işleme biçimine aykırı görünüyor, çünkü bu, bir sabit olarak bildirilse bile dilim değerinin değişebileceği anlamına geliyor:

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

En kötü yanı, dilimin tıpkı bir dizi gibi davranmasıdır. Swift'de değişmezlik beklentimiz olduğu göz önüne alındığında, dilimin abone değerlerinin herhangi bir uyarı olmaksızın değişebilmesi tehlikeli görünüyor:

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

Ancak temeldeki dizi çok büyük ölçüde değişirse, kancadan kurtulur:

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

6
Aslında, dilim işleri sadece senin dediğin gibi, diziler gibi. Swift dizileri, değişmez olarak bildirilse bile değiştirilebilir öğelere sahiptir . Örneğin, deneyin let arr = ["hello", "world", "goodbye"]; arr[0] = "bonjour". Çalıştığını göreceksin. Değişmez dizilerle, garip bir şekilde, yalnızca değişmez olan boyut , içerik değil. ( Swift Programlama Dilinde "Koleksiyonların Değişebilirliği" bölümüne bakın )
Matt Gibson

1
"Değişebilir öğeler" - Bu artık doğru değil
Alex Brown

14

Özet:

Yukarıdaki cevaplar Beta 3'e kadar doğruydu (ve gelecek sürümlerde tekrar değişebilir)

Dilim artık tıpkı bir dizi gibi davranıyor, ancak @matt'ın yukarıda da söylediği gibi, bir değişiklik yapılana kadar kaputun altındaki bir dizinin sığ bir kopyası. Dilimler (şimdi) orijinal değerlerin anlık görüntüsünü görür,

Ayrıca dilim sözdiziminin değiştiğine dikkat edin:

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

Misal:

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

Bu, python stili liste işlemeyi yapmak (bir listeyi diğerini yapmak için filtrelemek) daha basit olduğundan (IMHO) çok daha tek tip işlemeye izin verir. Matt'in Beta 3'ten önceki cevabına göre, bir dilimi eşlemek için geçici bir dizi oluşturmanız gerekiyordu. Yeni kod artık daha basit:

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

(adil olmak gerekirse, foo hala bir dilim)

Referans:

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

Önemli Değişiklikler, Çözülen Sorunlar, - Swift Dili, Paragraf 1

"Swift'deki Dizi, Dictionary ve String gibi tam değerli semantiğe sahip olacak şekilde tamamen yeniden tasarlandı ... m"

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.