Bagaimana cara kerja Substring String di Swift

354

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 Stringmemang 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.

Suragch
sumber
2
Bagi mereka yang ingin mendapatkan substring dari string stackoverflow.com/q/32305891/468724
Inder Kumar Rathore
atau subskrip string atau substring stackoverflow.com/questions/24092884/…
Leo Dabus

Jawaban:

831

masukkan deskripsi gambar di sini

Semua contoh berikut digunakan

var str = "Hello, playground"

Cepat 4

String mendapat perbaikan yang cukup besar di Swift 4. Ketika Anda mendapatkan beberapa substring dari sebuah String sekarang, Anda mendapatkan Substringjenis kembali daripada a String. 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.

let myString = String(mySubstring)

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 menggunakan String.Indexdan bukan Intindeks 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):

let index = str.index(str.startIndex, offsetBy: 5)
let mySubstring = str[..<index] // Hello

atau prefix:

let index = str.index(str.startIndex, offsetBy: 5)
let mySubstring = str.prefix(upTo: index) // Hello

atau bahkan lebih mudah:

let mySubstring = str.prefix(5) // Hello

Akhir dari sebuah string

Menggunakan subskrip:

let index = str.index(str.endIndex, offsetBy: -10)
let mySubstring = str[index...] // playground

atau suffix:

let index = str.index(str.endIndex, offsetBy: -10)
let mySubstring = str.suffix(from: index) // playground

atau bahkan lebih mudah:

let mySubstring = str.suffix(10) // playground

Perhatikan bahwa saat menggunakan suffix(from: index)saya harus menghitung kembali dari akhir dengan menggunakan -10. Itu tidak perlu ketika hanya menggunakan suffix(x), yang hanya mengambil xkarakter terakhir dari sebuah String.

Kisaran dalam sebuah string

Sekali lagi kami cukup menggunakan subskrip di sini.

let start = str.index(str.startIndex, offsetBy: 7)
let end = str.index(str.endIndex, offsetBy: -6)
let range = start..<end

let mySubstring = str[range]  // play

Konversi SubstringkeString

Jangan lupa, saat Anda siap untuk menyimpan substring, Anda harus mengonversinya menjadi a Stringsehingga memori string lama dapat dibersihkan.

let myString = String(mySubstring)

Menggunakan Intekstensi indeks?

Saya ragu untuk menggunakan Intekstensi 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 menggunakan Intindeks. Masih String.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.Indexdi masa depan. Tetapi sampai mereka saya memilih untuk menggunakan API mereka. Ini membantu saya untuk mengingat bahwa manipulasi String bukan hanya Intpencarian indeks sederhana .

Suragch
sumber
9
Terima kasih untuk desctription. Uprates layak baik. Apple terlalu rumit ini. Substring semudah string.substring [dari ... ke].
Teddy
Penjelasan yang sangat bagus. kecuali satu hal kecil garbage collected;-) Saya harap orang di sini tahu bahwa tidak ada pengumpulan sampah di Swift.
Christian Anchor Dampf
@ChristianAnchorDampf, Terima kasih telah meluangkan waktu untuk berkomentar. Saya mengambil pengumpulan sampah. Bagaimana kata-kata baru?
Suragch
Benar-benar jawaban yang luar biasa pak !!
davidev
194

Saya benar-benar frustrasi pada model akses String Swift: semuanya harus menjadi Index. Yang saya inginkan adalah mengakses karakter ke-i dari string menggunakan Int, bukan indeks canggung dan memajukan (yang terjadi berubah dengan setiap rilis utama). Jadi saya membuat ekstensi ke String:

extension String {
    func index(from: Int) -> Index {
        return self.index(startIndex, offsetBy: from)
    }

    func substring(from: Int) -> String {
        let fromIndex = index(from: from)
        return String(self[fromIndex...])
    }

    func substring(to: Int) -> String {
        let toIndex = index(from: to)
        return String(self[..<toIndex])
    }

    func substring(with r: Range<Int>) -> String {
        let startIndex = index(from: r.lowerBound)
        let endIndex = index(from: r.upperBound)
        return String(self[startIndex..<endIndex])
    }
}

let str = "Hello, playground"
print(str.substring(from: 7))         // playground
print(str.substring(to: 5))           // Hello
print(str.substring(with: 7..<11))    // play
Kode Berbeda
sumber
5
Indeks sangat berguna karena karakter dapat lebih dari satu byte. Cobalet str = "🇨🇭🇩🇪🇺🇸Hello" print(str.substring(to: 2))
vadian
112
Ya, saya mengerti bahwa karakter (yaitu cluster grapheme yang diperluas ) dapat mengambil banyak byte. Frustrasi saya adalah mengapa kita harus menggunakan metode memajukan indeks verbose untuk mengakses karakter string. Mengapa tim Swift tidak bisa menambahkan beberapa kelebihan ke Core Library untuk memisahkannya. Jika saya mengetik 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?
Kode Berbeda
6
@RenniePet Saya percaya Apple mengenali masalah dan perubahan akan datang. Sesuai halaman Swift Evolution di GitHub: "Swift 4 berupaya menjadikan string lebih kuat dan lebih mudah digunakan, sambil mempertahankan kebenaran Unicode secara default". Ini tidak jelas tetapi mari kita tetap berharap
Kode Berbeda
3
@CodeDifferent mengapa apple tidak menambahkan akses karakter subskrip? Agar orang mengerti bahwa itu hal buruk untuk dilakukan. Pada dasarnya jika Anda akan melakukan untuk saya di 0..string.count menggunakan subskrip yang akan menjadi loop ganda, karena di bawah tudung indeks harus melalui setiap byte string untuk mencari tahu yang merupakan karakter berikutnya. Jika Anda mengulang menggunakan indeks, Anda mengulangi string hanya sekali. Btw, benci ini sendiri, tapi itu alasan di balik subskrip tidak tersedia di string dengan cepat.
Raimundas Sakalauskas
4
@RaimundasSakalauskas argumen itu tidak terbang oleh saya. C # memiliki kebenaran Unicode dan bilangan bulat integer, yang sangat nyaman. Di Swift 1, Apple ingin pengembang menggunakan countElement(str)untuk menemukan panjangnya. Di Swift 3, Apple membuat string yang tidak sesuai Sequencedan memaksa semua orang untuk menggunakannya str.characters. Orang-orang ini tidak takut melakukan perubahan. Keras kepala mereka pada bilangan bulat bilangan bulat sangat sulit dipahami
Kode Berbeda
103

Ekstensi Swift 5:

extension String {
    subscript(_ range: CountableRange<Int>) -> String {
        let start = index(startIndex, offsetBy: max(0, range.lowerBound))
        let end = index(start, offsetBy: min(self.count - range.lowerBound, 
                                             range.upperBound - range.lowerBound))
        return String(self[start..<end])
    }

    subscript(_ range: CountablePartialRangeFrom<Int>) -> String {
        let start = index(startIndex, offsetBy: max(0, range.lowerBound))
         return String(self[start...])
    }
}

Pemakaian:

let s = "hello"
s[0..<3] // "hel"
s[3...]  // "lo"

Atau unicode:

let s = "😎🤣😋"
s[0..<1] // "😎"
Lou Zell
sumber
2
Jauh lebih baik, terima kasih telah mengirim ekstensi ini! Saya pikir berasal dari Python, Swift jauh lebih sulit daripada yang diperlukan untuk terbiasa. Tampaknya bagi orang yang pergi ke arah lain dari Objective C ke Swift ada konfirmasi lebih positif.
user3064009
1
@Leon, saya baru saja menghapusnya. Sebelum 4.1, counthanya tersedia padaself.characters
Lou Zell
1
Apakah ada gotchas yang harus diperhatikan dengan ekstensi khusus ini? Mengapa Apple tidak melakukan hal seperti ini?
Andz
1
@ Andz ini sangat tidak efisien. Ini dimulai dari awal string - dua kali - dan harus mengurai setiap karakter dari sana ke "rentang" - dua kali.
kareman
3
Anda juga perlu menambahkan ekstensi yang membutuhkan aCountableClosedRange<Int> jika Anda ingin menulis mis s[0...2].
Chris Frederick
24

Swift 4 & 5:

extension String {
  subscript(_ i: Int) -> String {
    let idx1 = index(startIndex, offsetBy: i)
    let idx2 = index(idx1, offsetBy: 1)
    return String(self[idx1..<idx2])
  }

  subscript (r: Range<Int>) -> String {
    let start = index(startIndex, offsetBy: r.lowerBound)
    let end = index(startIndex, offsetBy: r.upperBound)
    return String(self[start ..< end])
  }

  subscript (r: CountableClosedRange<Int>) -> String {
    let startIndex =  self.index(self.startIndex, offsetBy: r.lowerBound)
    let endIndex = self.index(startIndex, offsetBy: r.upperBound - r.lowerBound)
    return String(self[startIndex...endIndex])
  }
}

Bagaimana cara menggunakannya:

"abcde" [0] -> "a"

"abcde" [0 ... 2] -> "abc"

"abcde" [2 .. <4] -> "cd"

Souf ROCHDI
sumber
20

Cepat 4

Dalam 4 cepat Stringsesuai dengan Collection. Alih-alih substring, kita sekarang harus menggunakan subscript.Jadi jika Anda hanya ingin memotong kata "play"dari "Hello, playground", Anda bisa melakukannya seperti ini:

var str = "Hello, playground"
let start = str.index(str.startIndex, offsetBy: 7)
let end = str.index(str.endIndex, offsetBy: -6)
let result = str[start..<end] // The result is of type Substring

Sangat menarik untuk mengetahui, bahwa hal itu akan memberi Anda Substringbukan String. Ini cepat dan efisien karena Substringberbagi 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:

let newString = String(result)

Anda dapat menemukan informasi lebih lanjut tentang Substringkelas baru di [Dokumentasi Apple]. 1

Jadi, jika Anda misalnya mendapatkan Rangehasil dari NSRegularExpression, Anda dapat menggunakan ekstensi berikut:

extension String {

    subscript(_ range: NSRange) -> String {
        let start = self.index(self.startIndex, offsetBy: range.lowerBound)
        let end = self.index(self.startIndex, offsetBy: range.upperBound)
        let subString = self[start..<end]
        return String(subString)
    }

}
gebirgsbärbel
sumber
Kode Anda akan macet jika range.upperBound> panjang string. Juga, penggunaan sampel akan sangat membantu juga, karena saya tidak terbiasa dengan subskrip di Swift. Anda dapat memasukkan sesuatu seperti datePartOnly = "2018-01-04-08: 00" [NSMakeRange (0, 10)]. Selain itu, jawaban yang sangat bagus, +1 :).
dcp
sekarang ini adalah hal yang aneh ini: text[Range( nsRange , in: text)!]
Fattie
10

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.

func substring(string: String, fromIndex: Int, toIndex: Int) -> String? {
    if fromIndex < toIndex && toIndex < string.count /*use string.characters.count for swift3*/{
        let startIndex = string.index(string.startIndex, offsetBy: fromIndex)
        let endIndex = string.index(string.startIndex, offsetBy: toIndex)
        return String(string[startIndex..<endIndex])
    }else{
        return nil
    }
}

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

Nikesh Jha
sumber
9

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:

let rString = cString.substringToIndex(2)
let gString = (cString.substringFromIndex(2) as NSString).substringToIndex(2)
let bString = (cString.substringFromIndex(4) as NSString).substringToIndex(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:

let rString = String(cString.characters.prefix(2))
cString = String(cString.characters.dropFirst(2))
let gString = String(cString.characters.prefix(2))
cString = String(cString.characters.dropFirst(2))
let bString = String(cString.characters.prefix(2))

Saya harap ini berkontribusi ...

Rio Bautista
sumber
1
Nah, menangani masalah yang rumit bukan berarti solusinya bisa elegan. Sekali lagi, saya juga mengerti masalahnya, tetapi seluruh kelas String dan menanganinya hanya mengerikan.
inexcitus
5

Frustrasi yang sama, ini seharusnya tidak sulit ...

Saya mengkompilasi contoh ini untuk mendapatkan posisi substring dari teks yang lebih besar:

//
// Play with finding substrings returning an array of the non-unique words and positions in text
//
//

import UIKit

let Bigstring = "Why is it so hard to find substrings in Swift3"
let searchStrs : Array<String>? = ["Why", "substrings", "Swift3"]

FindSubString(inputStr: Bigstring, subStrings: searchStrs)


func FindSubString(inputStr : String, subStrings: Array<String>?) ->    Array<(String, Int, Int)> {
    var resultArray : Array<(String, Int, Int)> = []
    for i: Int in 0...(subStrings?.count)!-1 {
        if inputStr.contains((subStrings?[i])!) {
            let range: Range<String.Index> = inputStr.range(of: subStrings![i])!
            let lPos = inputStr.distance(from: inputStr.startIndex, to: range.lowerBound)
            let uPos = inputStr.distance(from: inputStr.startIndex, to: range.upperBound)
            let element = ((subStrings?[i])! as String, lPos, uPos)
            resultArray.append(element)
        }
    }
    for words in resultArray {
        print(words)
    }
    return resultArray
}

mengembalikan ("Mengapa", 0, 3) ("substring", 26, 36) ("Swift3", 40, 46)

Tinggi Dane
sumber
3
Itu adalah beberapa kode, tetapi tidak benar-benar menjelaskan bagaimana pengindeksan dan substring string bekerja di swift3.
Robert
5

Saya baru di Swift 3, tetapi mencari Stringsintaks (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:

let s = "abcdefghi"
let i = 2
print (s[s.index(s.startIndex, offsetBy:i)])
// print c

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:

let f = 6
print (s[s.index(s.startIndex, offsetBy:i )..<s.index(s.startIndex, offsetBy:f+1 )])
//print cdefg

Untuk substring (rentang) dari string menggunakan String.substring (rentang) kita bisa mendapatkan substring menggunakan kode di bawah ini:

print (s.substring (with:s.index(s.startIndex, offsetBy:i )..<s.index(s.startIndex, offsetBy:f+1 ) ) )
//print cdefg

Catatan:

  1. I-th dan f-th dimulai dengan 0.

  2. Untuk f-th, saya menggunakan offsetBY: f + 1, karena rentang penggunaan berlangganan .. <(operator setengah terbuka), tidak termasuk posisi f-th.

  3. Tentu saja harus menyertakan kesalahan validasi seperti indeks tidak valid.

Nelson Mizutani
sumber
5

Swift 4+

extension String {
    func take(_ n: Int) -> String {
        guard n >= 0 else {
            fatalError("n should never negative")
        }
        let index = self.index(self.startIndex, offsetBy: min(n, self.count))
        return String(self[..<index])
    }
}

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:

let text = "Hello, World!"
let substring = text.take(5) //Hello
Peter Kreinz
sumber
4

Saya berpikir cukup mekanis. Berikut adalah dasar-dasarnya ...

Swift 4 Swift 5

  let t = "abracadabra"

  let start1 = t.index(t.startIndex, offsetBy:0)
  let   end1 = t.index(t.endIndex, offsetBy:-5)
  let start2 = t.index(t.endIndex, offsetBy:-5)
  let   end2 = t.index(t.endIndex, offsetBy:0)

  let t2 = t[start1 ..< end1]
  let t3 = t[start2 ..< end2]                

  //or a shorter form 

  let t4 = t[..<end1]
  let t5 = t[start2...]

  print("\(t2) \(t3) \(t)")
  print("\(t4) \(t5) \(t)")

  // result:
  // abraca dabra abracadabra

Hasilnya adalah substring, artinya itu adalah bagian dari string asli. Untuk mendapatkan string terpisah yang penuh sesak, gunakan saja mis

    String(t3)
    String(t4)

Inilah yang saya gunakan:

    let mid = t.index(t.endIndex, offsetBy:-5)
    let firstHalf = t[..<mid]
    let secondHalf = t[mid...]
t1ser
sumber
3

Cepat 4

extension String {
    subscript(_ i: Int) -> String {
        let idx1 = index(startIndex, offsetBy: i)
        let idx2 = index(idx1, offsetBy: 1)
        return String(self[idx1..<idx2])
    }
}

let s = "hello"

s[0]    // h
s[1]    // e
s[2]    // l
s[3]    // l
s[4]    // o
FlowUI. SimpleUITesting.com
sumber
2

Saya membuat ekstensi sederhana untuk ini (Swift 3)

extension String {
    func substring(location: Int, length: Int) -> String? {
        guard characters.count >= location + length else { return nil }
        let start = index(startIndex, offsetBy: location)
        let end = index(startIndex, offsetBy: location + length)
        return substring(with: start..<end)
    }
}
Lucas Algarra
sumber
2

Inilah implementasi yang lebih umum:

Teknik ini masih digunakan indexuntuk memenuhi standar Swift, dan menyiratkan Karakter penuh.

extension String
{
    func subString <R> (_ range: R) -> String? where R : RangeExpression, String.Index == R.Bound
    {
        return String(self[range])
    }

    func index(at: Int) -> Index
    {
        return self.index(self.startIndex, offsetBy: at)
    }
}

Untuk sub string dari karakter ke-3:

let item = "Fred looks funny"
item.subString(item.index(at: 2)...) // "ed looks funny"

Saya telah menggunakan unta subStringuntuk menunjukkan bahwa ia mengembalikan a Stringdan bukan a Substring.

Leslie Godwin
sumber
2

Membangun di atas saya perlu membagi string pada karakter non-cetak menjatuhkan karakter non-cetak. Saya mengembangkan dua metode:

var str = "abc\u{1A}12345sdf"
let range1: Range<String.Index> = str.range(of: "\u{1A}")!
let index1: Int = str.distance(from: str.startIndex, to: range1.lowerBound)
let start = str.index(str.startIndex, offsetBy: index1)
let end = str.index(str.endIndex, offsetBy: -0)
let result = str[start..<end] // The result is of type Substring
let firstStr = str[str.startIndex..<range1.lowerBound]

yang saya kumpulkan menggunakan beberapa jawaban di atas.

Karena String adalah koleksi saya kemudian melakukan hal berikut:

var fString = String()
for (n,c) in str.enumerated(){

*if c == "\u{1A}" {
    print(fString);
    let lString = str.dropFirst(n + 1)
    print(lString)
    break
   }
 fString += String(c)
}*

Yang bagi saya lebih intuitif. Mana yang terbaik? Saya tidak tahu. Keduanya bekerja dengan Swift 5

Jeremy Andrews
sumber
Terima kasih atas jawaban anda. Apakah ada yang berbeda dengan Strings in Swift 5? Saya belum punya waktu untuk bermain-main dengannya.
Suragch
Mereka berkata begitu tetapi saya belum memiliki kesempatan untuk melihatnya.
Jeremy Andrews
1

Cepat 4

"Substring" ( https://developer.apple.com/documentation/swift/substring ):

let greeting = "Hi there! It's nice to meet you! 👋"
let endOfSentence = greeting.index(of: "!")!
let firstSentence = greeting[...endOfSentence]
// firstSentence == "Hi there!"

Contoh String ekstensi:

private typealias HowDoYouLikeThatElonMusk = String
private extension HowDoYouLikeThatElonMusk {

    subscript(_ from: Character?, _ to: Character?, _ include: Bool) -> String? {
        if let _from: Character = from, let _to: Character = to {
            let dynamicSourceForEnd: String = (_from == _to ? String(self.reversed()) : self)
            guard let startOfSentence: String.Index = self.index(of: _from),
                let endOfSentence: String.Index = dynamicSourceForEnd.index(of: _to) else {
                return nil
            }

            let result: String = String(self[startOfSentence...endOfSentence])
            if include == false {
                guard result.count > 2 else {
                        return nil
                }
                return String(result[result.index(result.startIndex, offsetBy: 1)..<result.index(result.endIndex, offsetBy: -1)])
            }
            return result
        } else if let _from: Character = from {
            guard let startOfSentence: String.Index = self.index(of: _from) else {
                return nil
            }
            let result: String = String(self[startOfSentence...])
            if include == false {
                guard result.count > 1 else {
                    return nil
                }
                return String(result[result.index(result.startIndex, offsetBy: 1)...])
            }
            return result
        } else if let _to: Character = to {
            guard let endOfSentence: String.Index = self.index(of: _to) else {
                    return nil
            }
            let result: String = String(self[...endOfSentence])
            if include == false {
                guard result.count > 1 else {
                    return nil
                }
                return String(result[..<result.index(result.endIndex, offsetBy: -1)])
            }
            return result
        }
        return nil
    }
}

contoh menggunakan String ekstensi:

let source =                                   ">>>01234..56789<<<"
// include = true
var from =          source["3", nil, true]  //       "34..56789<<<"
var to =            source[nil, "6", true]  // ">>>01234..56"
var fromTo =        source["3", "6", true]  //       "34..56"
let notFound =      source["a", nil, true]  // nil
// include = false
from =              source["3", nil, false] //        "4..56789<<<"
to =                source[nil, "6", false] // ">>>01234..5"
fromTo =            source["3", "6", false] //        "4..5"
let outOfBounds =   source[".", ".", false] // nil

let str = "Hello, playground"
let hello = str[nil, ",", false] // "Hello"
CAHbl463
sumber
-1

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.

Wimukthi Rajapaksha
sumber
2
Ini salah. Karakter A dapat terdiri dari satu atau lebih byte. Ini hanya berfungsi dengan teks ascii.
Leo Dabus