Swift: Başlangıçtan son karakter dizinine kadar alt dize nasıl elde edilir


110

Bir dizgeyi başka bir dizgeye dönüştürmenin en iyi / en basit yolunu öğrenmek istiyorum, ancak yalnızca bir alt küme ile, baştan başlayıp bir karakterin son dizinine kadar.

Örneğin, "www.stackoverflow.com" u "www.stackoverflow" a dönüştürün. Hangi kod parçacığı bunu yapar ve en hızlısı olur mu? (Umarım bu bir tartışma getirmez, ancak Swift'de alt dizelerle nasıl başa çıkılacağına dair iyi bir ders bulamıyorum.

Yanıtlar:


202

Sadece geriye doğru erişiyorum

En iyi yolu kullanmak etmektir substringToIndexbirleştirilerek endIndexmülkiyet ve advanceküresel işlevi.

var string1 = "www.stackoverflow.com"

var index1 = advance(string1.endIndex, -4)

var substring1 = string1.substringToIndex(index1)

Arkadan başlayan bir ip aranıyor

Kullanım rangeOfStringve set optionsiçin.BackwardsSearch

var string2 = "www.stackoverflow.com"

var index2 = string2.rangeOfString(".", options: .BackwardsSearch)?.startIndex

var substring2 = string2.substringToIndex(index2!)

Uzantı yok, saf deyimsel Swift

Swift 2.0

advanceartık bir parçası Indexve deniyor advancedBy. Bunu şöyle yaparsın:

var string1 = "www.stackoverflow.com"

var index1 = string1.endIndex.advancedBy(-4)

var substring1 = string1.substringToIndex(index1)

Swift 3.0

Sen diyemezsin advancedBybir üzerinde Stringdeğişken boyut öğesi vardır çünkü. Kullanmalısın index(_, offsetBy:).

var string1 = "www.stackoverflow.com"

var index1 = string1.index(string1.endIndex, offsetBy: -4)

var substring1 = string1.substring(to: index1)

Birçok şeyin adı değiştirildi. Davalar camelCase'de yazılır startIndexoldu lowerBound.

var string2 = "www.stackoverflow.com"

var index2 = string2.range(of: ".", options: .backwards)?.lowerBound

var substring2 = string2.substring(to: index2!)

Ayrıca, zorla sarmayı önermem index2. İsteğe bağlı ciltleme veya kullanabilirsiniz map. Şahsen mapşunları kullanmayı tercih ederim :

var substring3 = index2.map(string2.substring(to:))

Swift 4

Swift 3 sürümü hala geçerlidir ancak artık dizin aralıkları olan abonelikleri kullanabilirsiniz:

let string1 = "www.stackoverflow.com"

let index1 = string1.index(string1.endIndex, offsetBy: -4)

let substring1 = string1[..<index1]

İkinci yaklaşım değişmeden kalır:

let string2 = "www.stackoverflow.com"

let index2 = string2.range(of: ".", options: .backwards)?.lowerBound

let substring3 = index2.map(string2.substring(to:))

1
Teşekkürler @ fpg1503. Bulmak istediğim cevap bu. Diğer cevaplar bana dildeki özellikleri öğretti veya hatırlattı, ancak problemimi çözmek için kullanacağım yol bu.
Jason Hocker

1
string1.endIndex.advancedBy(-4)Benim için Swift 2.0'ı kullanmak işe yarıyoradvance
Alex Koshy

92
Bunu basitçe yapmanın ciddi bir yolu yok mu?
devios1

12
@devios hepsi doğru. Swift için Objective-C'ye kıyasla minnettarım, ancak IMHO bu çılgınca garip koda neden olan endişeler, oradaki kod ve kodlayıcıların% 99'u için önemsiz. Daha da kötüsü, kendimiz için kötü kullanışlı uzantılar yazacağız. Düzenli geliştiriciler bu üst düzey endişeleri anlayamazlarsa, yazılım ürettiğimiz yaya endişeleriyle başa çıkmak için EN AZ bir ad-hoc API yazabilirler. Dönüşme eğilimi NSStringde açıkça kötü çünkü sonunda hepimiz Vakıf (eski) sınıflarından uzaklaşmak istiyoruz. Yani .... daha fazla ranting!
Dan Rosenstark

2
Swift 4'te yapabilirsiniz string1[..<index1]. Gerek yok string1.startIndex.
bauerMusic

26

Hızlı 3, XCode 8

func lastIndexOfCharacter(_ c: Character) -> Int? {
    return range(of: String(c), options: .backwards)?.lowerBound.encodedOffset
}

Yana advancedBy(Int)Swift 3 kullanım beri gitmiş String'ın yöntemiyle index(String.Index, Int). StringAlt dize ve arkadaşlarla bu uzantıya göz atın :

public extension String {

    //right is the first encountered string after left
    func between(_ left: String, _ right: String) -> String? {
        guard let leftRange = range(of: left), let rightRange = range(of: right, options: .backwards)
        , leftRange.upperBound <= rightRange.lowerBound
            else { return nil }

        let sub = self.substring(from: leftRange.upperBound)
        let closestToLeftRange = sub.range(of: right)!
        return sub.substring(to: closestToLeftRange.lowerBound)
    }

    var length: Int {
        get {
            return self.characters.count
        }
    }

    func substring(to : Int) -> String {
        let toIndex = self.index(self.startIndex, offsetBy: to)
        return self.substring(to: toIndex)
    }

    func substring(from : Int) -> String {
        let fromIndex = self.index(self.startIndex, offsetBy: from)
        return self.substring(from: fromIndex)
    }

    func substring(_ r: Range<Int>) -> String {
        let fromIndex = self.index(self.startIndex, offsetBy: r.lowerBound)
        let toIndex = self.index(self.startIndex, offsetBy: r.upperBound)
        return self.substring(with: Range<String.Index>(uncheckedBounds: (lower: fromIndex, upper: toIndex)))
    }

    func character(_ at: Int) -> Character {
        return self[self.index(self.startIndex, offsetBy: at)]
    }

    func lastIndexOfCharacter(_ c: Character) -> Int? {
        guard let index = range(of: String(c), options: .backwards)?.lowerBound else
        { return nil }
        return distance(from: startIndex, to: index)
    }
}

Swift 4 için GÜNCEL eklenti

public extension String {

    //right is the first encountered string after left
    func between(_ left: String, _ right: String) -> String? {
        guard
            let leftRange = range(of: left), let rightRange = range(of: right, options: .backwards)
            , leftRange.upperBound <= rightRange.lowerBound
            else { return nil }

        let sub = self[leftRange.upperBound...]
        let closestToLeftRange = sub.range(of: right)!            
        return String(sub[..<closestToLeftRange.lowerBound])
    }

    var length: Int {
        get {
            return self.count
        }
    }

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

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

    func substring(_ r: Range<Int>) -> String {
        let fromIndex = self.index(self.startIndex, offsetBy: r.lowerBound)
        let toIndex = self.index(self.startIndex, offsetBy: r.upperBound)
        let indexRange = Range<String.Index>(uncheckedBounds: (lower: fromIndex, upper: toIndex))
        return String(self[indexRange])
    }

    func character(_ at: Int) -> Character {
        return self[self.index(self.startIndex, offsetBy: at)]
    }

    func lastIndexOfCharacter(_ c: Character) -> Int? {
        guard let index = range(of: String(c), options: .backwards)?.lowerBound else
        { return nil }
        return distance(from: startIndex, to: index)
    }
}

Kullanımı:

let text = "www.stackoverflow.com"
let at = text.character(3) // .
let range = text.substring(0..<3) // www
let from = text.substring(from: 4) // stackoverflow.com
let to = text.substring(to: 16) // www.stackoverflow
let between = text.between(".", ".") // stackoverflow
let substringToLastIndexOfChar = text.lastIndexOfCharacter(".") // 17

Not: Geliştiricilerin String.Indexdüz yerine uğraşmak zorunda kalması gerçekten tuhaf Int. Neden Stringsadece basit substring()yöntemlere sahip olmakla kalmayıp iç mekaniği dert etmeliyiz ?


encodedOffsetBu yorumu kontrol etmeyi ve bu stackoverflow.com/questions/34540185/… '
Leo Dabus

18

Bunu bir alt simge kullanarak yapardım (s[start..<end] ) :

Hızlı 3, 4, 5

let s = "www.stackoverflow.com"
let start = s.startIndex
let end = s.index(s.endIndex, offsetBy: -4)
let substring = s[start..<end] // www.stackoverflow

11

düzenleme / güncelleme:

Gelen sonradan Swift 4 veya (Xcode 10.0+) Yeni kullanabilirsiniz BidirectionalCollection yöntemi arasında (lastIndex :)

func lastIndex(of element: Element) -> Int?

let string = "www.stackoverflow.com"
if let lastIndex = string.lastIndex(of: ".") {
    let subString = string[..<lastIndex]  // "www.stackoverflow"
}

Bu harika bir cevap, ancak görünen o ki, Swift 2 ile bu özellik NSUrl'ye taşındı. Belki bu, gelecekte insanların bunu okumasına yardımcı olur ...
chuky

8

İşte bunu nasıl yapıyorum. Aynı şekilde yapabilir veya bu kodu fikirler için kullanabilirsiniz.

let s = "www.stackoverflow.com"
s.substringWithRange(0..<s.lastIndexOf("."))

İşte kullandığım uzantılar:

import Foundation
extension String {

  var length: Int {
    get {
      return countElements(self)
    }
  }

  func indexOf(target: String) -> Int {
    var range = self.rangeOfString(target)
    if let range = range {
      return distance(self.startIndex, range.startIndex)
    } else {
      return -1
    }
  }

  func indexOf(target: String, startIndex: Int) -> Int {
    var startRange = advance(self.startIndex, startIndex)        
    var range = self.rangeOfString(target, options: NSStringCompareOptions.LiteralSearch, range: Range<String.Index>(start: startRange, end: self.endIndex))
    if let range = range {
      return distance(self.startIndex, range.startIndex)
    } else {
      return -1
    }
  }

  func lastIndexOf(target: String) -> Int {
    var index = -1
    var stepIndex = self.indexOf(target)
    while stepIndex > -1 {
      index = stepIndex
      if stepIndex + target.length < self.length {
        stepIndex = indexOf(target, startIndex: stepIndex + target.length)
      } else {
        stepIndex = -1
      }
    }
    return index
  } 

  func substringWithRange(range:Range<Int>) -> String {
    let start = advance(self.startIndex, range.startIndex)
    let end = advance(self.startIndex, range.endIndex)
    return self.substringWithRange(start..<end)
  }

}

Kredi albertbori / Yaygın Swift String Uzantıları

Genel olarak, özellikle dizgi işleme, arama ve dilimleme gibi ihtiyaçlar için güçlü bir uzantı savunucusuyum.


2
Sanırım bunlar, Swift'deki String API'sini geliştirmek için Apple'ın yapması gereken bir şey.
ufuk çizgisi75489

2
Bu API aranıyor. Apple Swift, birçok temel API'den yoksundur. Çok karmaşık bir dil ve aynı zamanda tam değil. Swift saçmalık!
Loc

Referans verdiğiniz kütüphanenin Swift 3 sürümünün çatallanmış ve güncellenmiş bir sürümü: github.com/iamjono/SwiftString
RenniePet

5

String yerleşik alt dize özelliğine sahiptir:

extension String : Sliceable {
    subscript (subRange: Range<String.Index>) -> String { get }
}

İstediğiniz şey " bir karakterin ilk dizinine gitmek " ise, yerleşik find()işlevi kullanarak alt dizeyi elde edebilirsiniz :

var str = "www.stackexchange.com"
str[str.startIndex ..< find(str, ".")!] // -> "www"

Son dizini bulmak için uygulayabiliriz findLast().

/// Returns the last index where `value` appears in `domain` or `nil` if
/// `value` is not found.
///
/// Complexity: O(\ `countElements(domain)`\ )
func findLast<C: CollectionType where C.Generator.Element: Equatable>(domain: C, value: C.Generator.Element) -> C.Index? {
    var last:C.Index? = nil
    for i in domain.startIndex..<domain.endIndex {
        if domain[i] == value {
            last = i
        }
    }
    return last
}

let str = "www.stackexchange.com"
let substring = map(findLast(str, ".")) { str[str.startIndex ..< $0] } // as String?
// if "." is found, substring has some, otherwise `nil`

KATMA:

Belki BidirectionalIndexTypeözel sürümü findLastdaha hızlıdır:

func findLast<C: CollectionType where C.Generator.Element: Equatable, C.Index: BidirectionalIndexType>(domain: C, value: C.Generator.Element) -> C.Index? {
    for i in lazy(domain.startIndex ..< domain.endIndex).reverse() {
        if domain[i] == value {
            return i
        }
    }
    return nil
}

String için alt simge Swift 2.0'da mevcut görünmüyor, bunun yerini alacak bir şey biliyor musunuz?
Cory

Swift 4 veya sonrasında Index'i BidirectionalIndexType ile nasıl sınırlandırabileceğimi biliyor musunuz?
Leo Dabus

5

Bu uzantıları kullanabilirsiniz:

Swift 2.3

 extension String
    {
        func substringFromIndex(index: Int) -> String
        {
            if (index < 0 || index > self.characters.count)
            {
                print("index \(index) out of bounds")
                return ""
            }
            return self.substringFromIndex(self.startIndex.advancedBy(index))
        }

        func substringToIndex(index: Int) -> String
        {
            if (index < 0 || index > self.characters.count)
            {
                print("index \(index) out of bounds")
                return ""
            }
            return self.substringToIndex(self.startIndex.advancedBy(index))
        }

        func substringWithRange(start: Int, end: Int) -> String
        {
            if (start < 0 || start > self.characters.count)
            {
                print("start index \(start) out of bounds")
                return ""
            }
            else if end < 0 || end > self.characters.count
            {
                print("end index \(end) out of bounds")
                return ""
            }
            let range = Range(start: self.startIndex.advancedBy(start), end: self.startIndex.advancedBy(end))
            return self.substringWithRange(range)
        }

        func substringWithRange(start: Int, location: Int) -> String
        {
            if (start < 0 || start > self.characters.count)
            {
                print("start index \(start) out of bounds")
                return ""
            }
            else if location < 0 || start + location > self.characters.count
            {
                print("end index \(start + location) out of bounds")
                return ""
            }
            let range = Range(start: self.startIndex.advancedBy(start), end: self.startIndex.advancedBy(start + location))
            return self.substringWithRange(range)
        }
    }

Hızlı 3

extension String
{   
    func substring(from index: Int) -> String
    {
        if (index < 0 || index > self.characters.count)
        {
            print("index \(index) out of bounds")
            return ""
        }
        return self.substring(from: self.characters.index(self.startIndex, offsetBy: index))
    }

    func substring(to index: Int) -> String
    {
        if (index < 0 || index > self.characters.count)
        {
            print("index \(index) out of bounds")
            return ""
        }
        return self.substring(to: self.characters.index(self.startIndex, offsetBy: index))
    }

    func substring(start: Int, end: Int) -> String
    {
        if (start < 0 || start > self.characters.count)
        {
            print("start index \(start) out of bounds")
            return ""
        }
        else if end < 0 || end > self.characters.count
        {
            print("end index \(end) out of bounds")
            return ""
        }
        let startIndex = self.characters.index(self.startIndex, offsetBy: start)
        let endIndex = self.characters.index(self.startIndex, offsetBy: end)
        let range = startIndex..<endIndex

        return self.substring(with: range)
    }

    func substring(start: Int, location: Int) -> String
    {
        if (start < 0 || start > self.characters.count)
        {
            print("start index \(start) out of bounds")
            return ""
        }
        else if location < 0 || start + location > self.characters.count
        {
            print("end index \(start + location) out of bounds")
            return ""
        }
        let startIndex = self.characters.index(self.startIndex, offsetBy: start)
        let endIndex = self.characters.index(self.startIndex, offsetBy: start + location)
        let range = startIndex..<endIndex

        return self.substring(with: range)
    }
}

Kullanımı:

let string = "www.stackoverflow.com"        
let substring = string.substringToIndex(string.characters.count-4)

5

Swift 4:

extension String {

    /// the length of the string
    var length: Int {
        return self.characters.count
    }

    /// Get substring, e.g. "ABCDE".substring(index: 2, length: 3) -> "CDE"
    ///
    /// - parameter index:  the start index
    /// - parameter length: the length of the substring
    ///
    /// - returns: the substring
    public func substring(index: Int, length: Int) -> String {
        if self.length <= index {
            return ""
        }
        let leftIndex = self.index(self.startIndex, offsetBy: index)
        if self.length <= index + length {
            return self.substring(from: leftIndex)
        }
        let rightIndex = self.index(self.endIndex, offsetBy: -(self.length - index - length))
        return self.substring(with: leftIndex..<rightIndex)
    }

    /// Get substring, e.g. -> "ABCDE".substring(left: 0, right: 2) -> "ABC"
    ///
    /// - parameter left:  the start index
    /// - parameter right: the end index
    ///
    /// - returns: the substring
    public func substring(left: Int, right: Int) -> String {
        if length <= left {
            return ""
        }
        let leftIndex = self.index(self.startIndex, offsetBy: left)
        if length <= right {
            return self.substring(from: leftIndex)
        }
        else {
            let rightIndex = self.index(self.endIndex, offsetBy: -self.length + right + 1)
            return self.substring(with: leftIndex..<rightIndex)
        }
    }
}

aşağıdaki gibi test edebilirsiniz:

    print("test: " + String("ABCDE".substring(index: 2, length: 3) == "CDE"))
    print("test: " + String("ABCDE".substring(index: 0, length: 3) == "ABC"))
    print("test: " + String("ABCDE".substring(index: 2, length: 1000) == "CDE"))
    print("test: " + String("ABCDE".substring(left: 0, right: 2) == "ABC"))
    print("test: " + String("ABCDE".substring(left: 1, right: 3) == "BCD"))
    print("test: " + String("ABCDE".substring(left: 3, right: 1000) == "DE"))

Https://gitlab.com/seriyvolk83/SwiftEx kitaplığını kontrol edin . Bunları ve diğer yararlı yöntemleri içerir.


4

Başlangıç ​​dizininden karakterlerinden birinin son dizinine kadar bir dizenin alt dizesini almak istiyor musunuz? Öyleyse, aşağıdaki Swift 2.0+ yöntemlerinden birini seçebilirsiniz.

Gerektiren yöntemler Foundation

Bir karakterin son dizinini içeren bir alt dize alın:

import Foundation

let string = "www.stackoverflow.com"
if let rangeOfIndex = string.rangeOfCharacterFromSet(NSCharacterSet(charactersInString: "."), options: .BackwardsSearch) {
    print(string.substringToIndex(rangeOfIndex.endIndex))
}

// prints "www.stackoverflow."

Bir karakterin son dizinini İÇERMEYEN bir alt dize alın:

import Foundation

let string = "www.stackoverflow.com"
if let rangeOfIndex = string.rangeOfCharacterFromSet(NSCharacterSet(charactersInString: "."), options: .BackwardsSearch) {
    print(string.substringToIndex(rangeOfIndex.startIndex))
}

// prints "www.stackoverflow"

Bu işlemleri tekrarlamanız gerekiyorsa, genişletme Stringiyi bir çözüm olabilir:

import Foundation

extension String {
    func substringWithLastInstanceOf(character: Character) -> String? {
        if let rangeOfIndex = rangeOfCharacterFromSet(NSCharacterSet(charactersInString: String(character)), options: .BackwardsSearch) {
            return self.substringToIndex(rangeOfIndex.endIndex)
        }
        return nil
    }
    func substringWithoutLastInstanceOf(character: Character) -> String? {
        if let rangeOfIndex = rangeOfCharacterFromSet(NSCharacterSet(charactersInString: String(character)), options: .BackwardsSearch) {
            return self.substringToIndex(rangeOfIndex.startIndex)
        }
        return nil
    }
}

print("www.stackoverflow.com".substringWithLastInstanceOf("."))
print("www.stackoverflow.com".substringWithoutLastInstanceOf("."))

/*
prints:
Optional("www.stackoverflow.")
Optional("www.stackoverflow")
*/

GEREKTİRMEYEN yöntemler Foundation

Bir karakterin son dizinini içeren bir alt dize alın:

let string = "www.stackoverflow.com"
if let reverseIndex = string.characters.reverse().indexOf(".") {
    print(string[string.startIndex ..< reverseIndex.base])
}

// prints "www.stackoverflow."

Bir karakterin son dizinini İÇERMEYEN bir alt dize alın:

let string = "www.stackoverflow.com"
if let reverseIndex = string.characters.reverse().indexOf(".") {
    print(string[string.startIndex ..< reverseIndex.base.advancedBy(-1)])
}

// prints "www.stackoverflow"

Bu işlemleri tekrarlamanız gerekiyorsa, genişletme Stringiyi bir çözüm olabilir:

extension String {
    func substringWithLastInstanceOf(character: Character) -> String? {
        if let reverseIndex = characters.reverse().indexOf(".") {
            return self[self.startIndex ..< reverseIndex.base]
        }
        return nil
    }
    func substringWithoutLastInstanceOf(character: Character) -> String? {
        if let reverseIndex = characters.reverse().indexOf(".") {
            return self[self.startIndex ..< reverseIndex.base.advancedBy(-1)]
        }
        return nil
    }
}

print("www.stackoverflow.com".substringWithLastInstanceOf("."))
print("www.stackoverflow.com".substringWithoutLastInstanceOf("."))

/*
prints:
Optional("www.stackoverflow.")
Optional("www.stackoverflow")
*/

4

Dizini biliyorsanız bir alt dize almanın kolay ve kısa bir yolu:

let s = "www.stackoverflow.com"
let result = String(s.characters.prefix(17)) // "www.stackoverflow"

Dizininiz dizenin uzunluğunu aşarsa uygulamanın çökmesine neden olmaz:

let s = "short"
let result = String(s.characters.prefix(17)) // "short"

Her iki örnek de Swift 3'e hazırdır .


4

Takırdama ekleyen tek şey, tekrarlanan stringVar :

stringVar [ stringVar .index ( stringVar .startIndex, offsetBy: ...)

In Swift 4

Bir uzantı bunun bir kısmını azaltabilir:

extension String {

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

Ardından, kullanım:

let string = "abcde"

let to = string[..<string.index(at: 3)] // abc
let from = string[string.index(at: 3)...] // de

Bu tove fromtip Substring(veya String.SubSequance) olduğuna dikkat edilmelidir . Yeni dizeler ayırmazlar ve işleme için daha verimlidirler.

Bir Stringtürü geri almak Substringiçin şuna geri döndürülmesi gerekir String:

let backToString = String(from)

Burası sonunda bir dizenin tahsis edildiği yerdir.


3
func substr(myString: String, start: Int, clen: Int)->String

{
  var index2 = string1.startIndex.advancedBy(start)
  var substring2 = string1.substringFromIndex(index2)
  var index1 = substring2.startIndex.advancedBy(clen)
  var substring1 = substring2.substringToIndex(index1)

  return substring1   
}

substr(string1, start: 3, clen: 5)

3

Hızlı 3

let string = "www.stackoverflow.com"
let first3Characters = String(string.characters.prefix(3)) // www
let lastCharacters = string.characters.dropFirst(4) // stackoverflow.com (it would be a collection)

//or by index 
let indexOfFouthCharacter = olNumber.index(olNumber.startIndex, offsetBy: 4)
let first3Characters = olNumber.substring(to: indexOfFouthCharacter) // www
let lastCharacters = olNumber.substring(from: indexOfFouthCharacter) // .stackoverflow.com

Anlamak için iyi bir makale , neden buna ihtiyacımız var?


2

String'i iki alt dize yöntemiyle genişlettim. Alt dizeyi bir başlangıç ​​/ bitiş aralığı veya başlangıç ​​/ uzunluk ile şu şekilde çağırabilirsiniz:

var bcd = "abcdef".substring(1,to:3)
var cde = "abcdef".substring(2,to:-2)
var cde = "abcdef".substring(2,length:3)

extension String {
  public func substring(from:Int = 0, var to:Int = -1) -> String {
    if to < 0 {
        to = self.length + to
    }
    return self.substringWithRange(Range<String.Index>(
        start:self.startIndex.advancedBy(from),
        end:self.startIndex.advancedBy(to+1)))
  }
  public func substring(from:Int = 0, length:Int) -> String {
    return self.substringWithRange(Range<String.Index>(
        start:self.startIndex.advancedBy(from),
        end:self.startIndex.advancedBy(from+length)))
  }
}

self.length artık mevcut değil. Bunu uzantıya eklemeniz gerekiyor (Andrewz, lütfen kodu güncelleyin; başka bir yanıt göndermek istemiyorum): public func length () -> Int {return self.lengthOfBytesUsingEncoding (NSUTF16StringEncoding)}
philippe

1

Swift 2.0 Aşağıdaki kod XCode 7.2'de test edilmiştir. Lütfen alttaki ekli ekran görüntüsüne bakın

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        var mainText = "http://stackoverflow.com"

        var range = Range(start: mainText.startIndex.advancedBy(7), end: mainText.startIndex.advancedBy(24))
        var subText = mainText.substringWithRange(range)


        //OR Else use below for LAST INDEX

        range = Range(start: mainText.startIndex.advancedBy(7), end: mainText.endIndex)
        subText = mainText.substringWithRange(range)
    }
}

1

Swift 5'de

İhtiyacımız var String.IndexIndex'i temsil etmek için basit Int değeri yerine .

Ayrıca Swift'den String(değer türü) subString almaya çalıştığımızda , aslında Sequenceprotokol ile yinelememiz gerektiğini unutmayın String.SubSequence;String type .

Geri dönmek Stringiçin String.SubSequencekullanString(subString)

Aşağıdaki Örnek:

    let string = "https://stackoverflow.com"
    let firstIndex = String.Index(utf16Offset: 0, in: string)
    let lastIndex = String.Index(utf16Offset: 6, in: string)
    let subString = String(string[firstIndex...lastIndex])

0

İçin Swift 2.0 , bu gibi:

var string1 = "www.stackoverflow.com"
var index1 = string1.endIndex.advancedBy(-4)
var substring1 = string1.substringToIndex(index1)

Belki değiştirmişlerdir, ancak 'gelişmişBy' ('gelişmiş'
Wedge Martin

0

Andrewz'un gönderisini Swift 2.0 (ve belki Swift 3.0) ile uyumlu hale getirmek için değiştirdim. Benim mütevazi görüşüme göre, bu uzantının anlaşılması daha kolaydır ve diğer dillerde (PHP gibi) mevcut olanlara benzer .

extension String {

    func length() -> Int {
        return self.lengthOfBytesUsingEncoding(NSUTF16StringEncoding)
    }
    func substring(from:Int = 0, to:Int = -1) -> String {
       var nto=to
        if nto < 0 {
            nto = self.length() + nto
        }
        return self.substringWithRange(Range<String.Index>(
           start:self.startIndex.advancedBy(from),
           end:self.startIndex.advancedBy(nto+1)))
    }
    func substring(from:Int = 0, length:Int) -> String {
        return self.substringWithRange(Range<String.Index>(
            start:self.startIndex.advancedBy(from),
            end:self.startIndex.advancedBy(from+length)))
    }
}

0

Ayrıca Swift 4 için basit bir String uzantısı oluşturuyorum:

extension String {
    func subStr(s: Int, l: Int) -> String { //s=start, l=lenth
        let r = Range(NSRange(location: s, length: l))!
        let fromIndex = self.index(self.startIndex, offsetBy: r.lowerBound)
        let toIndex = self.index(self.startIndex, offsetBy: r.upperBound)
        let indexRange = Range<String.Index>(uncheckedBounds: (lower: fromIndex, upper: toIndex))

        return String(self[indexRange])
     }
}

Böylece kolayca şöyle diyebilirsiniz:

"Hallo world".subStr(s: 1, l: 3) //prints --> "all"

0

Bu Int-basedgeçici çözümü deneyin :

extension String {
    // start and end is included
    func intBasedSubstring(_ start: Int, _ end: Int) -> String {
        let endOffset: Int = -(count - end - 1)
        let startIdx = self.index(startIndex, offsetBy: start)
        let endIdx = self.index(endIndex, offsetBy: endOffset)
        return String(self[startIdx..<endIdx])
    }
}

Not: Bu sadece bir pratiktir. Sınırı kontrol etmiyor. İhtiyaçlarınıza uyacak şekilde değiştirin.


-1

İşte Swift'de alt dizeyi almanın basit bir yolu

import UIKit

var str = "Hello, playground" 
var res = NSString(string: str)
print(res.substring(from: 4))
print(res.substring(to: 10))

OP, önceden tanımlanmış kodlanmış değerler kullanılarak alt dizenin nasıl elde edileceğini değil, "Başlangıçtan karakterin son dizinine nasıl alt dize alınır" diye sorar.
Eric Aya

Bu orijinal örnekti: "www.stackoverflow.com" u "www.stackoverflow" a dönüştürün. Baştan sona bir alt dize istiyorsanız, yapacak bir şey yoktur, yani sonuç olduğu gibi giriş dizesidir. Lütfen yukarıdaki cevabın kullanışlılığını geri yükleyin.
ZagorTeNej
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.