Saya telah memperbarui beberapa kode lama saya dan jawaban dengan Swift 3 tetapi ketika saya sampai di Swift Strings dan Indexing dengan substring hal-hal menjadi membingungkan.
Secara khusus saya mencoba yang berikut:
let str = "Hello, playground"
let prefixRange = str.startIndex..<str.startIndex.advancedBy(5)
let prefix = str.substringWithRange(prefixRange)
di mana baris kedua memberi saya kesalahan berikut
Nilai tipe 'String' tidak memiliki anggota 'substringWithRange'
Saya melihat bahwa String
memang ada metode berikut sekarang:
str.substring(to: String.Index)
str.substring(from: String.Index)
str.substring(with: Range<String.Index>)
Ini benar-benar membingungkan saya pada awalnya jadi saya mulai bermain-main dengan indeks dan jangkauan . Ini adalah pertanyaan dan jawaban tindak lanjut untuk substring. Saya menambahkan jawaban di bawah ini untuk menunjukkan bagaimana mereka digunakan.
Jawaban:
Semua contoh berikut digunakan
Cepat 4
String mendapat perbaikan yang cukup besar di Swift 4. Ketika Anda mendapatkan beberapa substring dari sebuah String sekarang, Anda mendapatkan
Substring
jenis kembali daripada aString
. Kenapa ini? String adalah tipe nilai dalam Swift. Itu berarti jika Anda menggunakan satu String untuk membuat yang baru, maka itu harus disalin. Ini bagus untuk stabilitas (tidak ada orang lain yang akan mengubahnya tanpa sepengetahuan Anda) tetapi buruk untuk efisiensi.Substring, di sisi lain, adalah referensi kembali ke String asli dari mana asalnya. Berikut adalah gambar dari dokumentasi yang menggambarkan hal itu.
Tidak perlu menyalin sehingga jauh lebih efisien untuk digunakan. Namun, bayangkan Anda mendapat Substring sepuluh karakter dari String satu juta karakter. Karena Substring mereferensikan String, sistem harus berpegangan pada seluruh String selama Substring ada. Jadi, setiap kali Anda selesai memanipulasi Substring Anda, konversikan ke String.
Ini akan menyalin hanya substring dan memori yang memegang String lama dapat direklamasi . Substring (sebagai tipe) dimaksudkan untuk berumur pendek.
Peningkatan besar lainnya di Swift 4 adalah bahwa Strings adalah Collections (lagi). Itu berarti bahwa apa pun yang dapat Anda lakukan untuk Koleksi, Anda dapat lakukan ke String (gunakan subskrip, beralih ke karakter, filter, dll).
Contoh berikut menunjukkan cara mendapatkan substring di Swift.
Mendapatkan substring
Anda bisa mendapatkan substring dari string dengan menggunakan subscript atau beberapa metode lainnya (misalnya,
prefix
,suffix
,split
). Anda masih perlu menggunakanString.Index
dan bukanInt
indeks untuk rentang tersebut. (Lihat jawaban saya yang lain jika Anda membutuhkan bantuan.)Awal dari sebuah string
Anda dapat menggunakan subskrip (perhatikan kisaran satu sisi Swift 4):
atau
prefix
:atau bahkan lebih mudah:
Akhir dari sebuah string
Menggunakan subskrip:
atau
suffix
:atau bahkan lebih mudah:
Perhatikan bahwa saat menggunakan
suffix(from: index)
saya harus menghitung kembali dari akhir dengan menggunakan-10
. Itu tidak perlu ketika hanya menggunakansuffix(x)
, yang hanya mengambilx
karakter terakhir dari sebuah String.Kisaran dalam sebuah string
Sekali lagi kami cukup menggunakan subskrip di sini.
Konversi
Substring
keString
Jangan lupa, saat Anda siap untuk menyimpan substring, Anda harus mengonversinya menjadi a
String
sehingga memori string lama dapat dibersihkan.Menggunakan
Int
ekstensi indeks?Saya ragu untuk menggunakan
Int
ekstensi indeks berdasarkan setelah membaca artikel Strings in Swift 3 oleh Airspeed Velocity dan Ole Begemann. Meskipun dalam Swift 4, Strings adalah koleksi, tim Swift sengaja tidak menggunakanInt
indeks. MasihString.Index
. Ini ada hubungannya dengan Karakter Swift yang terdiri dari berbagai jumlah titik kode Unicode. Indeks aktual harus dihitung secara unik untuk setiap string.Saya harus mengatakan, saya harap tim Swift menemukan cara untuk abstrak
String.Index
di masa depan. Tetapi sampai mereka saya memilih untuk menggunakan API mereka. Ini membantu saya untuk mengingat bahwa manipulasi String bukan hanyaInt
pencarian indeks sederhana .sumber
garbage collected
;-) Saya harap orang di sini tahu bahwa tidak ada pengumpulan sampah di Swift.Saya benar-benar frustrasi pada model akses String Swift: semuanya harus menjadi
Index
. Yang saya inginkan adalah mengakses karakter ke-i dari string menggunakanInt
, bukan indeks canggung dan memajukan (yang terjadi berubah dengan setiap rilis utama). Jadi saya membuat ekstensi keString
:sumber
let str = "🇨🇭🇩🇪🇺🇸Hello"
print(str.substring(to: 2))
str[5]
, saya ingin mengakses karakter di indeks 5, apa pun karakter itu muncul atau berapa banyak byte yang dibutuhkan. Bukankah Swift semua tentang produktivitas pengembang?countElement(str)
untuk menemukan panjangnya. Di Swift 3, Apple membuat string yang tidak sesuaiSequence
dan memaksa semua orang untuk menggunakannyastr.characters
. Orang-orang ini tidak takut melakukan perubahan. Keras kepala mereka pada bilangan bulat bilangan bulat sangat sulit dipahamiEkstensi Swift 5:
Pemakaian:
Atau unicode:
sumber
count
hanya tersedia padaself.characters
CountableClosedRange<Int>
jika Anda ingin menulis miss[0...2]
.Swift 4 & 5:
Bagaimana cara menggunakannya:
sumber
Cepat 4
Dalam 4 cepat
String
sesuai denganCollection
. Alih-alihsubstring
, kita sekarang harus menggunakansubscript.
Jadi jika Anda hanya ingin memotong kata"play"
dari"Hello, playground"
, Anda bisa melakukannya seperti ini:Sangat menarik untuk mengetahui, bahwa hal itu akan memberi Anda
Substring
bukanString
. Ini cepat dan efisien karenaSubstring
berbagi penyimpanannya dengan String asli. Namun berbagi memori dengan cara ini juga dapat dengan mudah menyebabkan kebocoran memori.Inilah sebabnya mengapa Anda harus menyalin hasilnya ke String baru, setelah Anda ingin membersihkan String asli. Anda dapat melakukan ini menggunakan konstruktor normal:
Anda dapat menemukan informasi lebih lanjut tentang
Substring
kelas baru di [Dokumentasi Apple]. 1Jadi, jika Anda misalnya mendapatkan
Range
hasil dariNSRegularExpression
, Anda dapat menggunakan ekstensi berikut:sumber
text[Range( nsRange , in: text)!]
Berikut adalah fungsi yang mengembalikan substring dari substring yang diberikan saat indeks awal dan akhir disediakan. Untuk referensi lengkap, Anda dapat mengunjungi tautan yang diberikan di bawah ini.
Berikut ini tautan ke posting blog yang telah saya buat untuk menangani manipulasi string dengan cepat. Manipulasi string dalam cepat (Mencakup juga cepat 4)
Atau Anda dapat melihat intisari ini di github
sumber
Saya mendapat reaksi awal yang sama. Saya juga frustasi pada bagaimana sintaks dan objek berubah begitu drastis dalam setiap rilis utama.
Namun, saya menyadari dari pengalaman bagaimana saya akhirnya selalu menderita akibat mencoba melawan "perubahan" seperti berurusan dengan karakter multi-byte yang tidak dapat dihindari jika Anda melihat audiens global.
Jadi saya memutuskan untuk mengenali dan menghargai upaya yang dilakukan oleh para insinyur Apple dan melakukan bagian saya dengan memahami pola pikir mereka ketika mereka datang dengan pendekatan "mengerikan" ini.
Alih-alih membuat ekstensi yang hanya solusi untuk membuat hidup Anda lebih mudah (saya tidak mengatakan itu salah atau mahal), mengapa tidak mencari tahu bagaimana Strings sekarang dirancang untuk bekerja.
Sebagai contoh, saya memiliki kode ini yang berfungsi pada Swift 2.2:
dan setelah berhenti berusaha untuk membuat pendekatan yang sama berfungsi misalnya menggunakan Substring, saya akhirnya memahami konsep memperlakukan Strings sebagai kumpulan dua arah yang akhirnya saya dapatkan dengan versi kode yang sama:
Saya harap ini berkontribusi ...
sumber
Frustrasi yang sama, ini seharusnya tidak sulit ...
Saya mengkompilasi contoh ini untuk mendapatkan posisi substring dari teks yang lebih besar:
mengembalikan ("Mengapa", 0, 3) ("substring", 26, 36) ("Swift3", 40, 46)
sumber
Saya baru di Swift 3, tetapi mencari
String
sintaks (indeks) untuk analogi, saya pikir indeks seperti "pointer" yang dibatasi oleh string dan Int dapat membantu sebagai objek independen. Menggunakan sintaks dasar + offset, maka kita bisa mendapatkan karakter ke-i dari string dengan kode di bawah ini:Untuk rentang karakter (indeks) dari string menggunakan string (rentang) sintaksis yang bisa kita dapatkan dari karakter ke-ke-ke-ke-ke-ke-ke-ke-them dengan kode di bawah ini:
Untuk substring (rentang) dari string menggunakan String.substring (rentang) kita bisa mendapatkan substring menggunakan kode di bawah ini:
Catatan:
I-th dan f-th dimulai dengan 0.
Untuk f-th, saya menggunakan offsetBY: f + 1, karena rentang penggunaan berlangganan .. <(operator setengah terbuka), tidak termasuk posisi f-th.
Tentu saja harus menyertakan kesalahan validasi seperti indeks tidak valid.
sumber
Swift 4+
Mengembalikan urutan n karakter pertama, atau seluruh string jika string lebih pendek. (terinspirasi oleh: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/take.html )
Contoh:
sumber
Saya berpikir cukup mekanis. Berikut adalah dasar-dasarnya ...
Swift 4 Swift 5
Hasilnya adalah substring, artinya itu adalah bagian dari string asli. Untuk mendapatkan string terpisah yang penuh sesak, gunakan saja mis
Inilah yang saya gunakan:
sumber
Cepat 4
sumber
Saya membuat ekstensi sederhana untuk ini (Swift 3)
sumber
Inilah implementasi yang lebih umum:
Teknik ini masih digunakan
index
untuk memenuhi standar Swift, dan menyiratkan Karakter penuh.Untuk sub string dari karakter ke-3:
Saya telah menggunakan unta
subString
untuk menunjukkan bahwa ia mengembalikan aString
dan bukan aSubstring
.sumber
Membangun di atas saya perlu membagi string pada karakter non-cetak menjatuhkan karakter non-cetak. Saya mengembangkan dua metode:
yang saya kumpulkan menggunakan beberapa jawaban di atas.
Karena String adalah koleksi saya kemudian melakukan hal berikut:
Yang bagi saya lebih intuitif. Mana yang terbaik? Saya tidak tahu. Keduanya bekerja dengan Swift 5
sumber
Cepat 4
"Substring" ( https://developer.apple.com/documentation/swift/substring ):
Contoh String ekstensi:
contoh menggunakan String ekstensi:
sumber
Swift 5
let desiredIndex: Int = 7 let substring = str[String.Index(encodedOffset: desiredIndex)...]
Variabel substring ini akan memberikan Anda hasilnya.
Cukup di sini Int dikonversi menjadi Indeks dan kemudian Anda dapat membagi string. Kecuali Anda akan mendapatkan kesalahan.
sumber