String alt dizesi Swift'te nasıl çalışır?


354

Swift 3 ile bazı eski kodlarımı ve cevaplarımı güncelliyorum ama Swift Strings ve alt dizelerle İndeksleme'ye geldiğimde işler kafa karıştırıyordu.

Özellikle aşağıdakileri deniyordum:

let str = "Hello, playground"
let prefixRange = str.startIndex..<str.startIndex.advancedBy(5)
let prefix = str.substringWithRange(prefixRange)

ikinci satır bana şu hatayı veriyor

'String' türünün değeri 'substringWithRange' üyesi yok

StringŞimdi şu yöntemleri olduğunu görüyorum :

str.substring(to: String.Index)
str.substring(from: String.Index)
str.substring(with: Range<String.Index>)

Bunlar ilk başta beni gerçekten şaşırttı, bu yüzden indeks ve aralık etrafında oynamaya başladım . Bu, alt dize için bir takip sorusu ve cevabıdır. Nasıl kullanıldıklarını göstermek için aşağıya bir cevap ekliyorum.


2
Alt

veya alt simge dizesi veya alt dizesi stackoverflow.com/questions/24092884/…
Leo Dabus

Yanıtlar:


832

resim açıklamasını buraya girin

Aşağıdaki örneklerin tümü

var str = "Hello, playground"

Hızlı 4

Swift 4'te dizeler oldukça büyük bir revizyon aldı. Şimdi bir String'den bir alt dize aldığınızda, a Substringyerine bir tür alırsınız String. Bu neden? Dizeler Swift'teki değer türleridir. Bu, yeni bir tane yapmak için bir Dize kullanırsanız, o zaman kopyalanması gerekir. Bu istikrar için iyidir (başka kimse sizin bilginiz olmadan değiştirmeyecektir) ama verimlilik için kötüdür.

Diğer yandan, bir Alt dize, geldiği orijinal Dize'ye bir referanstır. İşte bunu gösteren belgelerden bir resim .

Kopyalamaya gerek yoktur, bu nedenle kullanımı çok daha verimlidir. Bununla birlikte, bir milyon karakterlik String'den on karakterlik bir Substring aldığınızı düşünün. Alt Dize Dizeye başvuruda bulunduğundan, alt Dizenin etrafında olduğu sürece sistemin tüm Dize'ye bağlı kalması gerekir. Böylece, Substring'inizi manipüle etmeyi bitirdiğinizde onu bir String'e dönüştürün.

let myString = String(mySubstring)

Bu sadece alt dizgiyi kopyalar ve eski String'i tutan bellek geri alınabilir . Alt dizeler (tip olarak) kısa ömürlüdür.

Swift 4'teki bir başka büyük gelişme, Dizelerin Koleksiyonlar (yine) olmasıdır. Bu, bir Koleksiyonda her ne yapabilirseniz yapın, bir String'e yapabilirsiniz (abonelik kullanın, karakterler üzerinde yineleme, filtre vb.).

Aşağıdaki örnekler Swift'te nasıl alt dize alacağınızı gösterir.

Alt dizeleri alma

Sen (örneğin, alt simgeler veya diğer yöntemlerle bir dizi kullanarak bir dize bir alt dizeyi alabilirsiniz prefix, suffix, split). Yine de , aralık için String.Indexbir Intdizin değil , kullanmanız gerekir . ( Bununla ilgili yardıma ihtiyacınız olursa diğer cevabımı görün .)

Bir dizenin başlangıcı

Bir alt simge kullanabilirsiniz (Swift 4 tek taraflı aralığa dikkat edin):

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

veya prefix:

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

veya daha da kolay:

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

Dizenin sonu

Abonelikleri kullanma:

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

veya suffix:

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

veya daha da kolay:

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

suffix(from: index)Ben kullanırken son kullanarak geri saymak zorunda olduğunu unutmayın -10. Sadece bir Dize'nin suffix(x)son xkarakterlerini alan sadece kullanırken bu gerekli değildir .

Bir dizedeki aralık

Yine burada sadece abonelikler kullanıyoruz.

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

Şuraya dönüştürülüyor Substring:String

Unutmayın, alt Stringdizenizi kaydetmeye hazır olduğunuzda, eski dizenin belleğinin temizlenebilmesi için bunu dizeye dönüştürmelisiniz .

let myString = String(mySubstring)

Bir Intdizin uzantısı mı kullanıyorsunuz?

Airspeed Velocity ve Ole Begemann tarafından Swift 3'te DizelerInt makalesini okuduktan sonra temel bir dizin uzantısı kullanmaktan çekinmeyin. Swift 4'te, Dizeler koleksiyon olsa da, Swift ekibi özellikle endeks kullanmamıştır. Hala öyle . Bu, Swift Karakterlerin değişen sayıda Unicode kod noktasından oluşmasıyla ilgilidir. Gerçek indeks, her dize için benzersiz bir şekilde hesaplanmalıdır.IntString.Index

Söylemeliyim ki, umarım Swift ekibi String.Indexgelecekte soyutlamak için bir yol bulur . Ancak onlara kadar API'larını kullanmayı tercih ediyorum. Dize manipülasyonlarının sadece basit Intdizin aramaları olmadığını hatırlamama yardımcı olur .


9
Açılış için teşekkürler. Haklı yükselişler. Apple bunu fazla karmaşıklaştırdı. Alt dize string.substring [... den] e kadar kolay olmalıdır.
Teddy

Gerçekten iyi bir açıklama. küçük bir şey hariç garbage collected;-) Umarım burada insanlar Swift'te çöp toplama olmadığını bilirler.
Christian Anchor Dampf

@ChristianAnchorDampf, Yorum yapmak için zaman ayırdığınız için teşekkür ederiz. Çöp topladım. Yeni ifade nasıl?
Ocak'ta Suragch

Ne harika bir cevap efendim !!
davidev

194

Swift'in String erişim modelinde gerçekten sinirliyim: her şey bir olmak zorunda Index. Tüm istediğim, Intbeceriksiz dizin ve ilerleyen (her büyük sürümde değişiyor olur) kullanarak dizenin i-karakterine erişmek için . Bu yüzden bir uzantı yaptım 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

5
Bir karakter birden fazla bayt olabileceğinden dizinler çok kullanışlıdır . Deneyinlet str = "🇨🇭🇩🇪🇺🇸Hello" print(str.substring(to: 2))
vadian

112
Evet, bir karakterin ( genişletilmiş grafik kümesi ) birden çok bayt alabileceğini anlıyorum . Hayal kırıklığım neden bir dizenin karakterlerine erişmek için ayrıntılı dizin ilerletme yöntemini kullanmamız gerektiğidir. Swift ekibi neden Çekirdek Kütüphane'ye soyutlamak için bazı aşırı yüklemeler ekleyemiyor? str[5]Yazarsam, dizin 5'teki karaktere, bu karakter ne olursa olsun veya kaç bayt alırsa erişmek istiyorum. Swift, geliştiricinin üretkenliği ile ilgili değil mi?
Farklı Kod

6
@RenniePet Apple'ın sorunu tanıdığına ve değişikliklerin geldiğine inanıyorum. GitHub'daki Swift Evrim sayfasına göre: "Swift 4, varsayılan olarak Unicode doğruluğunu korurken, dizeleri daha güçlü ve kullanımı daha kolay hale getirmeye çalışıyor". Bu belirsiz ama umutlarımızı devam
Code Different

3
Apple neden alt simge karakteri erişimi eklemedi? Böylece insanlar bunun kötü bir şey olduğunu anlarlar. Temelde, çift döngü olacak abonelikleri kullanarak 0..string.count için i yaparsanız, başlık dizininin altında bir sonraki karakterin hangisi olduğunu bulmak için dizenin her baytından geçmesi gerekir. Dizin kullanarak döngü yaparsanız, dize üzerinden yalnızca bir kez yineleme yaparsınız. Btw, kendimden nefret ediyorum, ama altyazının arkasındaki sebep hızlı bir şekilde ipte bulunmuyor.
Raimundas Sakalauskas

4
@RaimundasSakalauskas bu argüman benim tarafımdan uçmuyor. C # hem Unicode doğruluğuna hem de tam sayı aboneliğine sahiptir, ki bu gerçekten uygundur. Swift 1'de Apple, geliştiricilerin countElement(str)uzunluğu bulmak için kullanmasını istedi . Swift 3'te, Apple dize uymayan Sequenceve herkesin kullanımına zorlandı str.characters. Bu adamlar değişiklik yapmaktan korkmuyorlar. Tamsayı aboneliği konusundaki
Code Different

104

Swift 5 Uzantısı:

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

Kullanımı:

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

Veya unicode:

let s = "😎🤣😋"
s[0..<1] // "😎"

2
Çok daha iyi, bu uzantıyı gönderdiğiniz için teşekkür ederiz! Bence Python'dan gelen Swift, alışmak için gerekenden çok daha zor. Hedef C'den Swift'e diğer yöne giden insanlar için daha olumlu bir onay var gibi görünüyor.
user3064009

1
@Leon'u yeni çıkardım. 4.1'den önce countsadeceself.characters
Lou Zell

1
Bu özel uzantıyla dikkat edilmesi gereken herhangi bir şey var mı? Apple neden böyle bir şey yapmadı?
Andz

1
@Andz çok verimsiz. Dizenin başından başlar - iki kez - ve oradaki her karakteri "aralık" - iki kez ayrıştırmak zorundadır.
kareman

3
Ayrıca, örneğin, yazmak istediğiniz bir alan adıCountableClosedRange<Int> eklemeniz gerekir s[0...2].
Chris Frederick

24

Swift 4 ve 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])
  }
}

Bu nasıl kullanılır:

"abcde" [0] -> "a"

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

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


20

Hızlı 4

Swift ise 4 Stringuygundur için Collection. Yerine substring, artık kullanmalısınız subscript.sadece kelime kesip istiyorsanız So "play"dan "Hello, playground"böyle yapabilirdi,:

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

Bilmek ilginçtir, bunu yapmak size bir Substringyerine bir verecek String. SubstringDepolama alanını orijinal Dize ile paylaştığı için bu hızlı ve etkilidir . Ancak hafızayı bu şekilde paylaşmak, hafıza sızıntılarına da yol açabilir.

Bu nedenle, orijinal Dizeyi temizlemek istediğinizde sonucu yeni bir Dizeye kopyalamanız gerekir. Bunu normal yapıcıyı kullanarak yapabilirsiniz:

let newString = String(result)

Yeni Substringsınıf hakkında daha fazla bilgiyi [Apple belgeleri] 'nde bulabilirsiniz . 1

Bu nedenle, örneğin bir Rangesonucu olarak a NSRegularExpressionalırsanız, aşağıdaki uzantıyı kullanabilirsiniz:

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

}

Range.upperBound> dize uzunluğu ise kodunuz kilitlenir. Ayrıca, Swift'teki aboneliklere aşina olmadığım için örnek bir kullanım da yararlı olurdu. DatePartOnly = "2018-01-04-08: 00" [NSMakeRange (0, 10)] gibi bir şey ekleyebilirsiniz. Bunun dışında çok güzel bir cevap, +1 :).
dcp

günümüzde bu garip şey: text[Range( nsRange , in: text)!]
Fattie

10

Başlangıç ​​ve bitiş endeksleri sağlandığında belirli bir alt dizenin alt dizesini döndüren bir işlev aşağıdadır. Tam referans için aşağıdaki bağlantıları ziyaret edebilirsiniz.

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

İşte hızlı bir şekilde dize manipülasyonu ile başa çıkmak için oluşturduğum blog yazısının bir bağlantısı. Hızlı dize işleme (Hızlı 4'ü de kapsar)

Veya bu özü github'da görebilirsiniz


9

Aynı başlangıç ​​reaksiyonunu yaşadım. Ben de her büyük sürümde sözdizimi ve nesnelerin nasıl bu kadar ciddi bir şekilde değiştiğini hayal kırıklığına uğrattı.

Ancak, deneyime göre, küresel bir kitleye bakıyorsanız kaçınılmaz olan çok baytlı karakterlerle uğraşmak gibi "değişim" ile mücadele etmenin sonuçlarına her zaman nasıl acı çektiğimi fark ettim.

Bu yüzden Apple mühendislerinin çabalarını tanımaya ve saygı duymaya karar verdim ve bu "korkunç" yaklaşımı ortaya koyduklarında zihniyetlerini anlayarak üzerime düşeni yaptım.

Hayatınızı kolaylaştırmak için sadece geçici bir çözüm olan uzantılar oluşturmak yerine (yanlış veya pahalı olduklarını söylemiyorum), neden Dizelerin şimdi çalışmak için tasarlandığını anlamıyorsunuz.

Örneğin, Swift 2.2 üzerinde çalışan bu kodu vardı:

let rString = cString.substringToIndex(2)
let gString = (cString.substringFromIndex(2) as NSString).substringToIndex(2)
let bString = (cString.substringFromIndex(4) as NSString).substringToIndex(2)

ve aynı yaklaşımı örneğin Alt Dizeleri kullanarak çalışmayı bıraktıktan sonra, sonunda Dizeleri aynı kodun bu sürümü ile sona eren iki yönlü bir koleksiyon olarak tedavi kavramını anladım:

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))

Umarım bu katkıda bulunur ...


1
Karmaşık bir problemle uğraşmak, çözümün zarif olabileceği anlamına gelmez. Yine, ben de sorunu anlamak, ama tüm String sınıfı ve onunla başa çıkmak sadece korkunç.
inexcitus

5

Aynı hayal kırıklığı, bu o kadar zor olmamalı ...

Daha büyük metinden alt dize (ler) için konum alma bu örneği derledi:

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

döndürür ("Neden", 0, 3) ("alt dizeler", 26, 36) ("Swift3", 40, 46)


3
Bu bir kod, ancak dize indeksleme ve alt dizelerin swift3'te nasıl çalıştığını gerçekten açıklamaz.
Robert

5

Swift 3'te yeniyim, ancak Stringbenzetme için (index) sözdizimine baktığımda, dizinin dize ile sınırlandırılmış bir "işaretçi" gibi olduğunu düşünüyorum ve Int bağımsız bir nesne olarak yardımcı olabilir. Base + offset sözdizimini kullanarak, i-th karakterini aşağıdaki kodla birlikte dizeden alabiliriz:

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

Dize (aralık) sözdizimini kullanarak dizeden bir dizi karakter (dizin) için i-th'den f-th karakterlerine aşağıdaki kodla ulaşabilirsiniz:

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

String.substring (aralık) kullanarak bir dizeden bir alt dize (aralık) için, aşağıdaki kodu kullanarak alt dizeyi alabiliriz:

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

Notlar:

  1. İ-th ve f-th 0 ile başlar.

  2. F-th için, offsetBY: f + 1 kullanıyorum, çünkü abonelik aralığı kullanılıyor .. <(yarı açık operatör), f-th konumunu içermiyor.

  3. Elbette geçersiz dizin gibi doğrulama hataları içermelidir.


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

İlk n karakterin bir dizisini veya dize daha kısaysa dizenin tamamını döndürür. (ilham alan: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/take.html )

Misal:

let text = "Hello, World!"
let substring = text.take(5) //Hello

4

Ben oldukça mekanik bir düşünce. İşte temel bilgiler ...

Hızlı 4 hızlı 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

Sonuç bir alt dize, yani orijinal dizenin bir parçası olduğu anlamına gelir. Tam bir ayrı ayrı dize elde etmek için sadece örn.

    String(t3)
    String(t4)

Ne kullanıyorum:

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

3

Hızlı 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

2

Bunun için basit bir uzantı oluşturdum (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)
    }
}

2

Heres daha genel bir uygulama:

Bu teknik hala indexSwift'in standartlarına uymak ve tam bir Karakter anlamına gelmek için kullanıyor .

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

3. karakterdeki dizeyi alt dizeye eklemek için:

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

Ben subStringbir Stringdeğil döndürür belirtmek için deve kullandım Substring.


2

Yukarıdakilere dayanarak, bir dizgeyi yazdırılmayan karakteri bırakarak yazdırılmayan bir karaktere bölmem gerekiyordu. İki yöntem geliştirdim:

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]

yukarıdaki cevaplardan bazılarını kullanarak bir araya getirdim.

Dize bir koleksiyon olduğu için aşağıdakileri yaptım:

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)
}*

Benim için daha sezgiseldi. Hangisi en iyisi? Her ikisinin Swift 5 ile çalıştığını söylemenin hiçbir yolu yok


Cevabınız için teşekkürler. Swift 5'teki Dizeler hakkında farklı bir şey var mı? Henüz onunla oynamak için zamanım olmadı.
Suresi

Öyle diyorlar ama buna bakma şansım olmadı.
Jeremy Andrews

1

Hızlı 4

"Alt dize" ( 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!"

Uzatma Dizesi Örneği:

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

Dize uzantısını kullanma örneği:

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"

-1

Swift 5
let desiredIndex: Int = 7 let substring = str[String.Index(encodedOffset: desiredIndex)...]
Bu alt dize değişkeni sonucu verecektir.
Basitçe burada Int Endeksi dönüştürülür ve sonra dizeleri bölebilirsiniz. Hatalar almadığınız sürece.


2
Bu yanlış. Bir Karakter bir veya daha fazla bayt içerebilir. Sadece ASCII metniyle çalışır.
Leo Dabus
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.