„Indeks dolny” jest niedostępny: nie może istnieć indeks dolny z CountableClosedRange , zapoznaj się z komentarzem do dokumentacji do dyskusji


W Swift 4 pojawia się ten błąd, gdy próbuję pobrać
Substring
z
String
przy użyciu składni indeksu dolnego.

Opcja „indeks dolny” jest niedostępna: nie może istnieć wiersz indeksu dolnego z wartością CountableClosedRange. Dyskusja zawiera komentarz do dokumentacji

Na przykład:
let myString: String = "foobar"
let mySubstring: Substring = myString[1..<3]

Dwa pytania:
  • Jak mogę rozwiązać ten błąd
  • Gdzie jest „komentarz do dokumentacji do dyskusji” wspomniany w błędzie

Zaproszony:
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

  • Jeśli chcesz używać indeksów dla ciągów, takich jak
    "palindrome" [1 .. & < 3]
    i
    "palindrome" [1 ... 3]
    , użyj tych rozszerzeń .


Swift 4

<pre class="lang-swift prettyprint-override">
extension String {
subscript (bounds: CountableClosedRange<Int>) -> String {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return String(self[start...end])
} subscript (bounds: CountableRange<Int>) -> String {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return String(self[start..<end])
}
}


Swift 3

W przypadku Swift 3 zamień na
return self [start ... end]
i
return self [start .. & < end]
.
<ol start="2">
[*]
Firma Apple nie wbudowała tego w język Swift, ponieważ definicja „znaku” zależy od sposobu kodowania ciągu. Znak może mieć od 8 do 64 bitów, a wartością domyślną jest zwykle UTF-16. Możesz określić inne kodowanie ciągów w
String.Index
.
[/*]
[/list]
To jest dokumentacja
https://github.com/apple/swift ... 23L15
odwołuje się do błędu Xcode.
Więcej o kodowaniu ciągów, takich jak UTF-8 i UTF-16
https://developer.apple.com/li ... .html
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Twoje pytanie (i odpowiedź własna) ma 2 problemy:
Subskrybowanie linii z
Int
nigdy nie było dostępne w standardowej bibliotece Swift. Ten kod nie był ważny, dopóki istniał Swift:
let mySubstring: Substring = myString[1..<3]

Nowy
String.Index (encodedOffset :)
zwraca indeks zakodowany w formacie UTF-16 (16-bitowy). Szybkie użycie ciągów

rozszerzony klaster grafemowy

który może zająć od 8 do 64 bitów, aby zapisać znak. Emoji robią bardzo dobre demo:
let myString = ""
let lowerBound = String.Index(encodedOffset: 1)
let upperBound = String.Index(encodedOffset: 3)
let mySubstring = myString[lowerBound..<upperBound]// Expected: Canadian and UK flags
// Actual : gibberish
print(mySubstring)

W rzeczywistości otrzymywanie
String.Index
nie zmieniło się w ogóle w Swift 4, na lepsze ani na gorsze:
let myString = ""
let lowerBound = myString.index(myString.startIndex, offsetBy: 1)
let upperBound = myString.index(myString.startIndex, offsetBy: 3)
let mySubstring = myString[lowerBound..<upperBound]print(mySubstring)
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

  • Jak mogę rozwiązać ten błąd
Ten błąd oznacza, że ​​nie możesz użyć Int w formacie indeksu - musisz użyć String.Index, który możesz zainicjować za pomocą encodedOffset Int.
let myString: String = "foobar"
let lowerBound = String.Index.init(encodedOffset: 1)
let upperBound = String.Index.init(encodedOffset: 3)
let mySubstring: Substring = myString[lowerBound..<upperBound]
<ol start="2">
[*]
Gdzie jest „komentarz do dokumentacji do dyskusji” wspomniany w błędzie?
[/*]
[/list]Jest na GitHubie w standardowym repozytorium biblioteki Swift w pliku o nazwie UnavailableStringAPIs.swift.gyb na dole zamkniętej szafki na dokumenty, która utknęła w opuszczonej szafie z napisem „Uważaj na lamparta” na drzwiach.

połączyć
https://github.com/apple/swift ... 23L15
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Możesz po prostu przekonwertować swój ciąg na tablicę znaków ...
let aryChar = Array(myString)

Otrzymujesz wtedy całą funkcjonalność tablicy ...
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Na podstawie odpowiedzi

p-sun
https://stackoverflow.com/a/46627527/709202
i

Justin Oroza
https://stackoverflow.com/a/55659545/709202, oto dwa rozszerzenia, które chronią przed nieprawidłowymi indeksami poza początkiem i końcem ciągu (te rozszerzenia również unikają ponownego skanowania ciągu od samego początku tylko po to, aby znaleźć indeks na końcu zakresu):
extension String { subscript(bounds: CountableClosedRange<Int>) -> String {
let lowerBound = max(0, bounds.lowerBound)
guard lowerBound < self.count else { return "" } let upperBound = min(bounds.upperBound, self.count-1)
guard upperBound >= 0 else { return "" } let i = index(startIndex, offsetBy: lowerBound)
let j = index(i, offsetBy: upperBound-lowerBound) return String(self[i...j])
} subscript(bounds: CountableRange<Int>) -> String {
let lowerBound = max(0, bounds.lowerBound)
guard lowerBound < self.count else { return "" } let upperBound = min(bounds.upperBound, self.count)
guard upperBound >= 0 else { return "" } let i = index(startIndex, offsetBy: lowerBound)
let j = index(i, offsetBy: upperBound-lowerBound) return String(self[i..<j])
}
}
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Oparte na

odpowiedź p-sun
https://stackoverflow.com/a/46627527/4188011

Swift 4

extension StringProtocol {
subscript(bounds: CountableClosedRange<Int>) -> SubSequence {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(start, offsetBy: bounds.count)
return self[start..<end]
} subscript(bounds: CountableRange<Int>) -> SubSequence {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(start, offsetBy: bounds.count)
return self[start..<end]
}
}

Istotne zmiany:
  • Teraz rozszerzenie to
    StringProtocol
    . Umożliwia to adoptującym, takim jak
    Substring
    , uzyskanie tych indeksów.
  • Końcowe indeksy są odsunięte od indeksu początkowych granic, a nie od początku wiersza. Zapobiega to dwukrotnemu przeskakiwaniu od początku
    String
    . Metoda
    index
    - to jest O (n), gdzie n jest przesunięciem względem i.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

extension String { subscript(bounds: CountableClosedRange<Int>) -> String {
let lowerBound = max(0, bounds.lowerBound)
guard lowerBound < self.count else { return "" } let upperBound = min(bounds.upperBound, self.count-1)
guard upperBound >= 0 else { return "" } let i = index(startIndex, offsetBy: lowerBound)
let j = index(i, offsetBy: upperBound-lowerBound) return String(self[i...j])
} subscript(bounds: CountableRange<Int>) -> String {
let lowerBound = max(0, bounds.lowerBound)
guard lowerBound < self.count else { return "" } ***let upperBound = min(bounds.upperBound, self.count-1)***
guard upperBound >= 0 else { return "" } let i = index(startIndex, offsetBy: lowerBound)
let j = index(i, offsetBy: upperBound-lowerBound) return String(self[i..<j])
}
}
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Otrzymujesz ten błąd, ponieważ wynik indeksu zawiera zakres
to
Substring?
, a nie
Substring
.
Powinieneś użyć następującego kodu:
let myString: String = "foobar"
let mySubstring: Substring? = myString[1..<3]

Aby odpowiedzieć na pytania, Zaloguj się lub Zarejestruj się