Jak mogę uzyskać n-ty znak ciągu? Próbowałem []
akcesorium brack ( ) bez powodzenia.
var string = "Hello, world!"
var firstChar = string[0] // Throws error
BŁĄD: „indeks dolny” jest niedostępny: nie można subskrybować ciągu znaków z Int, patrz komentarz do dokumentacji do dyskusji
swift
string
collections
character
Mohsen
źródło
źródło
var firstChar = string.index(string.startIndex, offsetBy: 0)
zamiaststring.startIndex
? Dla pierwszej postacistring[string.startIndex]
lub po prostustring.first
. Zauważ, że pierwsze podejście, które musisz sprawdzić, czy łańcuch jest pusty, drugie zwraca opcjonalneOdpowiedzi:
Uwaga: zapoznaj się z odpowiedzią Leo Dabusa dotyczącą prawidłowej implementacji Swift 4 i Swift 5.
Swift 4 lub nowszy
Ten
Substring
typ został wprowadzony w Swift 4, aby podciągi były szybsze i bardziej wydajne poprzez współdzielenie pamięci z oryginalnym ciągiem, więc to właśnie powinny zwrócić funkcje indeksu dolnego.Wypróbuj tutaj
Aby przekonwertować
Substring
na aString
, możesz po prostu to zrobićString(string[0..2])
, ale powinieneś to zrobić tylko wtedy, gdy planujesz zachować podciąg. W przeciwnym razie bardziej efektywne jest utrzymanie goSubstring
.Byłoby wspaniale, gdyby ktoś wymyślił dobry sposób na połączenie tych dwóch rozszerzeń w jedno. Próbowałem rozszerzyćUwaga: Ta odpowiedź została już zredagowana, jest poprawnie zaimplementowana i teraz działa również dla podciągów. Upewnij się, że używasz prawidłowego zakresu, aby uniknąć awarii podczas subskrybowania typu StringProtocol. Do indeksowania z zakresem, który nie spowoduje awarii przy wartościach spoza zakresu, możesz użyć tej implementacjiStringProtocol
bez powodzenia, ponieważindex
metoda tam nie istnieje.Dlaczego to nie jest wbudowane?
Komunikat o błędzie mówi „zobacz komentarz do dokumentacji do dyskusji” . Apple udostępnia następujące wyjaśnienie w pliku UnavailableStringAPIs.swift :
źródło
Cannot find an overload for 'advance' that accepts an argument list of type '(String.Index, T)'
...String.Index
iInt
nie są kompatybilne.Cannot subscript a value of type 'String'...
sprawdź tę odpowiedź: stackoverflow.com/a/31265316/649379Ambiguous use of 'subscript'
.fatal error: Can't form a Character from an empty String
Szybki 5.2
Musisz dodać to rozszerzenie String do swojego projektu (jest w pełni przetestowane):
Mimo że Swift zawsze miał gotowe rozwiązanie tego problemu (bez rozszerzenia String, które podałem poniżej), nadal zdecydowanie polecam użycie rozszerzenia. Dlaczego? Ponieważ zaoszczędziło mi to dziesiątki godzin bolesnej migracji z wczesnych wersji Swift, gdzie składnia String zmieniała się prawie w każdym wydaniu, ale wszystko, co musiałem zrobić, to zaktualizować implementację rozszerzenia w przeciwieństwie do refaktoryzacji całego projektu. Dokonaj swojego wyboru.
źródło
range.upperBound - range.lowerBound
narange.count
extension StringProtocol where Self: RangeReplaceableCollection { subscript(offset: Int) -> Element { get { return self[index(startIndex, offsetBy: offset)] } set { let start = index(startIndex, offsetBy: offset) replaceSubrange(start..<index(after: start), with: [newValue]) } } }
Właśnie wymyśliłem to fajne obejście
źródło
var firstChar = Array(string!)[0]
inaczej powie toadd arrayLiteral
Brak indeksowania przy użyciu liczb całkowitych, tylko przy użyciu
String.Index
. Głównie z liniową złożonością. Możesz także tworzyć zakresyString.Index
i uzyskiwać z nich podciągi.Swift 3.0
Swift 2.x
Pamiętaj, że nigdy nie możesz użyć indeksu (lub zakresu) utworzonego z jednego ciągu na drugi
źródło
String
indeksy są unikalne dla łańcucha. Wynika to z faktu, że różne łańcuchy mogą mieć różne wieloczęściowe UTF-16Characters
i / lub w różnych pozycjach, więc indeksy jednostek UTF-16 nie będą pasować, mogą spaść poza koniec lub punkt wewnątrz wieloczęściowego UTF-16Character
...
jest teraz..<
(w twoim zadaniurange
)var lastChar = string[string.endIndex.predecessor()]
Xcode 11 • Swift 5.1
Możesz rozszerzyć StringProtocol, aby indeks dolny był dostępny również dla podciągów:
Testowanie
źródło
return String(Array(characters)[range])
w Swift 3?Szybki 4
Ciąg o indeksie
Podciąg
Pierwsze n znaków
Ostatnie n znaków
Swift 2 i 3
** Ciąg według indeksu **
Swift 2
Szybki 3
SubString fromIndex toIndex
Swift 2
Szybki 3
Pierwsze n znaków
Ostatnie n znaków
źródło
Swift 2.0 od Xcode 7 GM Seed
Dla n-tego znaku zamień 0 na n-1.
Edycja: Swift 3.0
Uwaga: istnieją prostsze sposoby chwytania niektórych znaków w ciągu
na przykład
let firstChar = text.characters.first
źródło
Jeśli widzisz,
Cannot subscript a value of type 'String'...
użyj tego rozszerzenia:Szybki 3
Swift 2.3
Źródło: http://oleb.net/blog/2014/07/swift-strings/
źródło
Rozwiązanie Swift 2.2:
Poniższe rozszerzenie działa w Xcode 7, jest to połączenie tego rozwiązania i konwersji składni Swift 2.0.
źródło
Szybka klasa łańcuchowa nie zapewnia możliwości uzyskania znaku o określonym indeksie z uwagi na jego natywną obsługę znaków UTF. Zmienna długość znaku UTF w pamięci uniemożliwia skok bezpośrednio do znaku. Oznacza to, że za każdym razem musisz ręcznie zapętlić ciąg.
Możesz rozszerzyć String, aby zapewnić metodę, która będzie przechodzić między znakami aż do pożądanego indeksu
źródło
myString.bridgeToObjectiveC().characterAtIndex(0)
lub(string as NSString ).characterAtIndex(0)
zwraca wartość Int znakuNSString
metod dostępu do pojedynczych znaków z natywnego SwiftString
- oba używają różnych mechanizmów liczenia, dzięki czemu uzyskasz nieprzewidywalne wyniki przy wyższych znakach Unicode. Pierwsza metoda powinna być bezpieczna (po rozwiązaniu błędów Unicode Swift).Na marginesie, istnieje kilka funkcji, które można zastosować bezpośrednio do reprezentacji ciągu znaków w łańcuchu znaków, takie jak:
Wynik jest typu Postać, ale możesz rzucić go na Ciąg.
Albo to:
:-)
źródło
Szybki 4
Jest to prawdopodobnie najlepszy sposób na rozwiązanie tego problemu jednorazowo. Prawdopodobnie chcesz najpierw rzucić String jako tablicę, a następnie ponownie rzutować wynik jako String. W przeciwnym razie znak zostanie zwrócony zamiast łańcucha.
Przykład
String(Array("HelloThere")[1])
zwróci „e” jako ciąg.(Array("HelloThere")[1]
zwróci „e” jako postać.Swift nie pozwala na indeksowanie ciągów znaków jak tablic, ale wykonuje to zadanie w stylu brute-force.
źródło
Moje bardzo proste rozwiązanie:
Swift 4.1:
Swift 5.1:
źródło
let flags = "🇺🇸🇧🇷"
flags[String.Index(utf16Offset: 4, in: flags)] // "🇧🇷"
Możesz to zrobić, konwertując String na Array i uzyskując go według określonego indeksu za pomocą indeksu dolnego jak poniżej
źródło
Właśnie miałem ten sam problem. Po prostu zrób to:
źródło
NSString
.Swift3
Możesz użyć składni indeksu dolnego, aby uzyskać dostęp do znaku przy określonym indeksie ciągów.
Odwiedź https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/StringsAndCharacters.html
lub możemy wykonać rozszerzenie ciągu w Swift 4
STOSOWANIE:
źródło
Moje rozwiązanie jest w jednej linii, załóżmy, że cadena jest łańcuchem, a 4 to n-ta pozycja, którą chcesz:
Proste ... Przypuszczam, że Swift będzie zawierał więcej informacji na temat podciągów w przyszłych wersjach.
źródło
var charAtIndex = string[advance(string.startIndex, 10)]
w odpowiedzi Sulthana?Swift 3: inne rozwiązanie (testowane na placu zabaw)
Stosowanie:
źródło
Aktualizacja do szybkiego subString 2.0
źródło
Myślę, że szybką odpowiedzią na pierwszą postać może być:
Jest o wiele bardziej elegancki i wydajny niż:
Ale .. jeśli chcesz manipulować i wykonywać więcej operacji na ciągach, możesz pomyśleć o utworzeniu rozszerzenia .. istnieje jedno rozszerzenie z tym podejściem, jest dość podobne do tego, które już tu opublikowano:
}
ALE TO OKOLICZNY POMYSŁ !!
Poniższe rozszerzenie jest strasznie nieefektywne. Za każdym razem, gdy ciąg jest uzyskiwany za pomocą liczby całkowitej, uruchamiana jest funkcja O (n) w celu przyspieszenia początkowego indeksu. Uruchomienie pętli liniowej wewnątrz innej pętli liniowej oznacza, że przypadkowo pętla ta ma wartość O (n2) - wraz ze wzrostem długości łańcucha rośnie czas kwadratowy tej pętli.
Zamiast tego możesz użyć kolekcji ciągów znaków.
źródło
Szybki 3
Stosowanie
Pomocne wskazówki i porady programistyczne (napisane przeze mnie)
źródło
Pobierz i ustaw indeks (ciąg i podciąg) - Swift 4.2
Swift 4.2, Xcode 10
Oparłem swoją odpowiedź na odpowiedzi @alecarlson . Jedyna różnica polega można dostać
Substring
lubString
zwrócony (aw niektórych przypadkach pojedynczaCharacter
). Możesz takżeget
iset
indeks dolny. Wreszcie moje jest trochę bardziej kłopotliwe i dłuższe niż odpowiedź @alecarlson i jako takie sugeruję, abyś umieścił je w pliku źródłowym.Rozbudowa:
źródło
Szybki 4.2
Ta odpowiedź jest idealna, ponieważ rozszerza
String
i wszystkie jejSubsequences
(Substring
) w jednym rozszerzeniuStosowanie
źródło
start
iend
) zstartIndex
. Możesz po prostu skompensowaćend
indeks za pomocą range.count i przesunąćstart
indeksDo tej pory indeks dolny (_ :) jest niedostępny. Nie możemy tego zrobić
za pomocą ciągu znaków. Musimy podać ciąg „String.Index”. Ale w jaki sposób możemy w ten sposób podać własny numer indeksu, zamiast tego możemy użyć,
źródło
string[string.startIndex]
? BTW, kod nie zachowuje się poprawnie / kompiluje, ponieważ użyłeś dwóch różnych nazw zmiennych.Swift 4.2 lub nowszy
Indeksowanie zakresu i częściowego zakresu za pomocą
String
'sindices
właściwośćJako wariant ładnej odpowiedzi @LeoDabus , możemy dodać dodatkowe rozszerzenie
DefaultIndices
w celu umożliwienia nam powrotu doindices
właściwościString
przy wdrażaniu niestandardowych indeksów dolnych (wedługInt
zakresów specjalistycznych i zakresów częściowych) dla tego drugiego.Dzięki @LeoDabus za wskazanie mnie w kierunku wykorzystania tej
indices
właściwości jako (innej) alternatywy dlaString
subskrypcji!źródło
swiftenv
kiedy to robię, ale myślę, że wkrótce zostanie zaktualizowany do wersji 4.2.Swift 5.1.3:
Dodaj rozszerzenie String:
źródło
String
Typ Swift nie zapewnia znakucharacterAtIndex
metody, ponieważ istnieje kilka sposobów kodowania łańcucha Unicode. Czy korzystasz z UTF8, UTF16 lub czegoś innego?Możesz uzyskać dostęp do
CodeUnit
kolekcji, pobierając właściwościString.utf8
iString.utf16
. Możesz również uzyskać dostęp doUnicodeScalar
kolekcji, pobierając plikString.unicodeScalars
właściwość.W duchu
NSString
implementacji zwracamunichar
typ.źródło
Aby nakarmić temat i pokazać szybkie możliwości indeksu dolnego, oto krótki ciąg oparty na indeksie dolnym
Te metody są bezpieczne i nigdy nie przekraczają indeksów ciągów
źródło
Rozwiązanie typu python, które pozwala na użycie indeksu ujemnego,
możliwe:
Nawiasem mówiąc, może być warto przetransponować notację wycinka całego pytona
źródło
Możesz także przekonwertować ciąg znaków na tablicę znaków w następujący sposób:
Jest to sposób na uzyskanie znaku w określonym indeksie w stałym czasie.
Poniższy przykład nie działa w stałym czasie, ale wymaga czasu liniowego. Więc jeśli masz dużo wyszukiwania w Ciąg według indeksu, użyj powyższej metody.
źródło