Jak korzystać z indeksu dolnego odcinania łańcucha w Swift 4?

294

Mam następujący prosty kod napisany w Swift 3:

let str = "Hello, playground"
let index = str.index(of: ",")!
let newStr = str.substring(to: index)

Z Xcode 9 beta 5 otrzymuję następujące ostrzeżenie:

substring(to:)” jest przestarzałe: użyj Stringindeksu krojenia z operatorem „częściowy zakres od”.

Jak można zastosować ten indeks krojenia z częściowym zakresem w Swift 4?

Adrian
źródło
var str = "Hello, playground" let indexcut = str.firstIndex (of: ",") print (String (str [.. <indexcut!])) print (String (str [indexcut! ...]))
user1828845,

Odpowiedzi:

375

Powinieneś pozostawić jedną stronę pustą , stąd nazwa „zakres częściowy”.

let newStr = str[..<index]

To samo oznacza częściowy zasięg od operatorów, po prostu zostaw drugą stronę pustą:

let newStr = str[index...]

Należy pamiętać, że operatorzy zakresu zwracają a Substring. Jeśli chcesz przekonwertować go na ciąg, użyj Stringfunkcji inicjalizacji:

let newStr = String(str[..<index])

Możesz przeczytać więcej o nowych podciągach tutaj .

Tamás Sengel
źródło
8
str[..<index]zwraca a Substring. Jeśli chcesz newStrbyć String, musisz napisać:let newStr = "\(str[..<index])"
Lindemann
12
Korzystanie interpolacji ciąg z samodzielnego Substringjest prawdopodobnie nieco mylące, ponieważ to, czego naprawdę chce osiągnąć jest Stringinicjalizacji: let newStr = String(str[..<index]).
Gary
5
Kod gdzie moja wartość „indeks” był po prostu liczbą całkowitą daje komunikat o błędzie uaktualnianie Cannot subscript a value of type 'String' with an index of type 'PartialRangeUpTo<Int>'. Jakie rodzaje wartości należy tam zastosować?
ConfusionTowers
22
@ ConfusionTowers, indeksy Swift nie są liczbami całkowitymi i nie zmieniło się to w wersji 4. Prawdopodobnie będziesz potrzebować str[..<str.index(str.startIndex, offsetBy: 8)]czegoś takiego. Należy pamiętać, że str.indexjest to działanie w czasie liniowym w funkcji offsetBy.
zneak
6
@zneak Prawdopodobnie chceszstr.prefix(8)
Tim Vermeulen
264

Konwertuj podciąg (Swift 3) na przecinanie łańcuchów (Swift 4)

Przykłady w Swift 3, 4:

let newStr = str.substring(to: index) // Swift 3
let newStr = String(str[..<index]) // Swift 4

let newStr = str.substring(from: index) // Swift 3
let newStr = String(str[index...]) // Swift 4 

let range = firstIndex..<secondIndex // If you have a range
let newStr = = str.substring(with: range) // Swift 3
let newStr = String(str[range])  // Swift 4
Mohammad Sadegh Panadgoo
źródło
5
Perfecto i dzięki za podanie 3 i 4 przykładów obok siebie, znacznie ułatwia aktualizację mojego projektu!
Ethan Parker,
86

Swift 5, 4

Stosowanie

let text = "Hello world"
text[0] // H
text[...3] // "Hell"
text[6..<text.count] // world
text[NSRange(location: 6, length: 3)] // wor

Kod

import Foundation

public extension String {
  subscript(value: Int) -> Character {
    self[index(at: value)]
  }
}

public extension String {
  subscript(value: NSRange) -> Substring {
    self[value.lowerBound..<value.upperBound]
  }
}

public extension String {
  subscript(value: CountableClosedRange<Int>) -> Substring {
    self[index(at: value.lowerBound)...index(at: value.upperBound)]
  }

  subscript(value: CountableRange<Int>) -> Substring {
    self[index(at: value.lowerBound)..<index(at: value.upperBound)]
  }

  subscript(value: PartialRangeUpTo<Int>) -> Substring {
    self[..<index(at: value.upperBound)]
  }

  subscript(value: PartialRangeThrough<Int>) -> Substring {
    self[...index(at: value.upperBound)]
  }

  subscript(value: PartialRangeFrom<Int>) -> Substring {
    self[index(at: value.lowerBound)...]
  }
}

private extension String {
  func index(at offset: Int) -> String.Index {
    index(startIndex, offsetBy: offset)
  }
}
dimpiax
źródło
14
ta funkcja powinna być domyślnie szybkim zachowaniem.
Laimis
4
Zdecydowanie PR to w Swift lib: D
OhadM
2
To poprawka najbrzydszej części Swift.
Dmitry
@Dmitry komuś się to nie podoba, ponieważ ta odpowiedź ma -2. : D
dimpiax,
To zła odpowiedź, ponieważ operator indeksu dolnego ukrywa złożoność funkcji indeksu O (n). Dobry programujący interfejs API używa tylko indeksu dolnego do oznaczenia szybkiego wyszukiwania.
ragnarius
38

Krótszy w Swift 4/5:

var string = "123456"
string = String(string.prefix(3)) //"123"
string = String(string.suffix(3)) //"456"
ilnur
źródło
26

Konwersję kodu na Swift 4 można również wykonać w następujący sposób:

let str = "Hello, playground"
let index = str.index(of: ",")!
let substr = str.prefix(upTo: index)

Możesz użyć poniższego kodu, aby uzyskać nowy ciąg:

let newString = String(str.prefix(upTo: index))
Thyerri Mezzari
źródło
17

substring (z: indeks) Przekształcony na [indeks ...]

Sprawdź próbkę

let text = "1234567890"
let index = text.index(text.startIndex, offsetBy: 3)

text.substring(from: index) // "4567890"   [Swift 3]
String(text[index...])      // "4567890"   [Swift 4]
Legowisko
źródło
1
postacie są przestarzałe w Swift 4, myślę, że musisz zmienić przykład, aby uzyskać indeks dla Swift 4
AbuTaareq
To mi pomogło. tnx
user1105951
17

Swift5

(Metoda substringowa Javy):

extension String {
    func subString(from: Int, to: Int) -> String {
       let startIndex = self.index(self.startIndex, offsetBy: from)
       let endIndex = self.index(self.startIndex, offsetBy: to)
       return String(self[startIndex...endIndex])
    }
}

Stosowanie:

var str = "Hello, Nick Michaels"
print(str.subString(from:7,to:20))
// print Nick Michaels
August Lin
źródło
2
Nadal pracuje w Swift 5. Szukałem stylu podciągu Java ( fromaby to-1np "Hello".substring(1,4)zwrotów „ell”). Z małą modyfikacją ( startIndex..<endIndex) jest to najlepsze rozwiązanie, jakie do tej pory znalazłem, robi to dokładnie za pomocą zaledwie kilku linii kodu.
Neph
9

Niektóre przydatne rozszerzenia:

extension String {
    func substring(from: Int, to: Int) -> String {
        let start = index(startIndex, offsetBy: from)
        let end = index(start, offsetBy: to - from)
        return String(self[start ..< end])
    }

    func substring(range: NSRange) -> String {
        return substring(from: range.lowerBound, to: range.upperBound)
    }
}
Johannes
źródło
Interesujące, myślałem tak samo. Czy String (wiersz [„http: //” .endIndex ...]) jest wyraźniejszy niż przestarzały podciąg? line.substring (from: "http: //" .endIndex) może dopóki nie osiągną określonego celu niesamowitej obsługi napisów, nie powinni przestać używać podciągów.
possen
7

Przykład uppercasedFirstCharacterwłaściwości wygody w Swift3 i Swift4.

Właściwość uppercasedFirstCharacterNewpokazuje, jak korzystać z indeksu dolnego odcinania łańcucha w Swift4.

extension String {

   public var uppercasedFirstCharacterOld: String {
      if characters.count > 0 {
         let splitIndex = index(after: startIndex)
         let firstCharacter = substring(to: splitIndex).uppercased()
         let sentence = substring(from: splitIndex)
         return firstCharacter + sentence
      } else {
         return self
      }
   }

   public var uppercasedFirstCharacterNew: String {
      if characters.count > 0 {
         let splitIndex = index(after: startIndex)
         let firstCharacter = self[..<splitIndex].uppercased()
         let sentence = self[splitIndex...]
         return firstCharacter + sentence
      } else {
         return self
      }
   }
}

let lorem = "lorem".uppercasedFirstCharacterOld
print(lorem) // Prints "Lorem"

let ipsum = "ipsum".uppercasedFirstCharacterNew
print(ipsum) // Prints "Ipsum"
Vlad
źródło
1
Jeśli masz na myśli substring (with: range) -> self [range]
Arsen Vartbaronov
6

Możesz utworzyć własną metodę subString, używając rozszerzenia do klasy String, jak poniżej:

extension String {
    func subString(startIndex: Int, endIndex: Int) -> String {
        let end = (endIndex - self.count) + 1
        let indexStartOfText = self.index(self.startIndex, offsetBy: startIndex)
        let indexEndOfText = self.index(self.endIndex, offsetBy: end)
        let substring = self[indexStartOfText..<indexEndOfText]
        return String(substring)
    }
}
Chhaileng
źródło
Jeśli to zajmie endIndex, musi również być w stanie poradzić sobie z ograniczeniami.
Jay
5

Tworzenie SubString (przedrostek i przyrostek) z String przy użyciu Swift 4:

let str : String = "ilike"
for i in 0...str.count {
    let index = str.index(str.startIndex, offsetBy: i) // String.Index
    let prefix = str[..<index] // String.SubSequence
    let suffix = str[index...] // String.SubSequence
    print("prefix \(prefix), suffix : \(suffix)")
}

Wynik

prefix , suffix : ilike
prefix i, suffix : like
prefix il, suffix : ike
prefix ili, suffix : ke
prefix ilik, suffix : e
prefix ilike, suffix : 

Jeśli chcesz wygenerować podciąg między 2 indeksami, użyj:

let substring1 = string[startIndex...endIndex] // including endIndex
let subString2 = string[startIndex..<endIndex] // excluding endIndex
Ashis Laha
źródło
niech prefiks = str [... <index>] zamiast str [.. <index>] brakuje pojedynczej kropki.
AbuTaareq
@AbuTaareq, o którym mówisz? niech prefiks = str [.. <indeks], jest idealny. (ciąg prefiksu). Spróbuj na placu zabaw, aby uzyskać więcej kontekstu.
Ashis Laha,
4

Napisałem rozszerzenie ciągu w celu zastąpienia ciągu „String: subString:”

extension String {

    func sliceByCharacter(from: Character, to: Character) -> String? {
        let fromIndex = self.index(self.index(of: from)!, offsetBy: 1)
        let toIndex = self.index(self.index(of: to)!, offsetBy: -1)
        return String(self[fromIndex...toIndex])
    }

    func sliceByString(from:String, to:String) -> String? {
        //From - startIndex
        var range = self.range(of: from)
        let subString = String(self[range!.upperBound...])

        //To - endIndex
        range = subString.range(of: to)
        return String(subString[..<range!.lowerBound])
    }

}

Stosowanie : "Date(1511508780012+0530)".sliceByString(from: "(", to: "+")

Przykład wyniku : „1511508780012”

PS: Opcjonalni są zmuszeni do rozpakowania. W razie potrzeby dodaj kontrolę bezpieczeństwa typu.

autor: Jeevan
źródło
Uwaga: opcjonalni są zmuszeni do rozpakowania. w razie potrzeby dodaj kontrolę bezpieczeństwa typu.
autor: Jeevan
3

Podczas programowania często mam ciągi znaków z prostym A-Za-z i 0-9. Nie ma potrzeby wykonywania trudnych akcji indeksu. To rozszerzenie jest oparte na zwykłych starych funkcjach lewy / środkowy / prawy.

extension String {

    // LEFT
    // Returns the specified number of chars from the left of the string
    // let str = "Hello"
    // print(str.left(3))         // Hel
    func left(_ to: Int) -> String {
        return "\(self[..<self.index(startIndex, offsetBy: to)])"
    }

    // RIGHT
    // Returns the specified number of chars from the right of the string
    // let str = "Hello"
    // print(str.left(3))         // llo
    func right(_ from: Int) -> String {
        return "\(self[self.index(startIndex, offsetBy: self.length-from)...])"
    }

    // MID
    // Returns the specified number of chars from the startpoint of the string
    // let str = "Hello"
    // print(str.left(2,amount: 2))         // ll
    func mid(_ from: Int, amount: Int) -> String {
        let x = "\(self[self.index(startIndex, offsetBy: from)...])"
        return x.left(amount)
    }
}
Vincent
źródło
Świetny pomysł!! Smutne jest jednak to, że trzeba wyodrębnić funkcje Swift tylko dlatego, że ciągle zmieniają sposób działania. Chyba chcą, abyśmy wszyscy skupili się na konstrukcjach zamiast na produktywności. W każdym razie dokonałem drobnych aktualizacji twojego dobrego kodu: pastebin.com/ManWmNnW
Fredrik Johansson
2

za pomocą tej metody można uzyskać określony zakres ciągów. musisz przekazać indeks początkowy, a po tej całkowitej liczbie znaków, którą chcesz.

extension String{
    func substring(fromIndex : Int,count : Int) -> String{
        let startIndex = self.index(self.startIndex, offsetBy: fromIndex)
        let endIndex = self.index(self.startIndex, offsetBy: fromIndex + count)
        let range = startIndex..<endIndex
        return String(self[range])
    }
}
jayesh kanzariya
źródło
2

To jest moje rozwiązanie, bez ostrzeżenia, bez błędów, ale idealne

let redStr: String = String(trimmStr[String.Index.init(encodedOffset: 0)..<String.Index.init(encodedOffset: 2)])
let greenStr: String = String(trimmStr[String.Index.init(encodedOffset: 3)..<String.Index.init(encodedOffset: 4)])
let blueStr: String = String(trimmStr[String.Index.init(encodedOffset: 5)..<String.Index.init(encodedOffset: 6)])
Victor John
źródło
Używanie encodedOffsetjest uważane za szkodliwe i będzie przestarzałe .
Martin R
1

Mam nadzieję, że to pomoże trochę więcej:

var string = "123456789"

Jeśli chcesz podciągu po określonym indeksie.

var indexStart  =  string.index(after: string.startIndex )// you can use any index in place of startIndex
var strIndexStart   = String (string[indexStart...])//23456789

Jeśli chcesz podciąg po usunięciu łańcucha na końcu.

var indexEnd  =  string.index(before: string.endIndex)
var strIndexEnd   = String (string[..<indexEnd])//12345678

możesz także tworzyć indeksy z następującym kodem: -

var  indexWithOffset =  string.index(string.startIndex, offsetBy: 4)
Anurag Bhakuni
źródło
0

Mam nadzieję, że byłoby to pomocne.

extension String {
    func getSubString(_ char: Character) -> String {
        var subString = ""
        for eachChar in self {
            if eachChar == char {
                return subString
            } else {
                subString += String(eachChar)
            }
        }
        return subString
    }
}


let str: String = "Hello, playground"
print(str.getSubString(","))
Anand Verma
źródło
0
var str = "Hello, playground"
let indexcut = str.firstIndex(of: ",")
print(String(str[..<indexcut!]))
print(String(str[indexcut!...]))

Możesz spróbować w ten sposób i uzyskasz odpowiednie wyniki.

użytkownik1828845
źródło