Récupère le nième caractère d'une chaîne dans le langage de programmation Swift
Comment puis-je obtenir le nième caractère d'une chaîne? J'ai essayé support ([]
) accesseur sans chance.
var string = "Hello, world!"
var firstChar = string[0] // Throws error
30 réponses
Attention: veuillez consulter la réponse de Leo dabus pour une implémentation correcte pour Swift 4.
Swift 4
Le type Substring
a été introduit dans Swift 4 pour créer des sous-chaînes
plus rapide et plus efficace en partageant le stockage avec la chaîne d'origine, c'est donc ce que les fonctions d'indice devraient retourner.
Essayez-le ici
extension String {
subscript (i: Int) -> Character {
return self[index(startIndex, offsetBy: i)]
}
subscript (bounds: CountableRange<Int>) -> Substring {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[start ..< end]
}
subscript (bounds: CountableClosedRange<Int>) -> Substring {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[start ... end]
}
subscript (bounds: CountablePartialRangeFrom<Int>) -> Substring {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(endIndex, offsetBy: -1)
return self[start ... end]
}
subscript (bounds: PartialRangeThrough<Int>) -> Substring {
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[startIndex ... end]
}
subscript (bounds: PartialRangeUpTo<Int>) -> Substring {
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[startIndex ..< end]
}
}
extension Substring {
subscript (i: Int) -> Character {
return self[index(startIndex, offsetBy: i)]
}
subscript (bounds: CountableRange<Int>) -> Substring {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[start ..< end]
}
subscript (bounds: CountableClosedRange<Int>) -> Substring {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[start ... end]
}
subscript (bounds: CountablePartialRangeFrom<Int>) -> Substring {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(endIndex, offsetBy: -1)
return self[start ... end]
}
subscript (bounds: PartialRangeThrough<Int>) -> Substring {
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[startIndex ... end]
}
subscript (bounds: PartialRangeUpTo<Int>) -> Substring {
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[startIndex ..< end]
}
}
Pour convertir les Substring
en String
, vous pouvez simplement
faites String(string[0..2])
, mais vous ne devriez le faire que si
vous envisagez d' garder la sous-chaîne autour de. Sinon, c'est plus
efficace pour le garder un Substring
.
Ce serait génial si quelqu'un pouvait trouver un bon moyen de fusionner
ces deux extensions en une seule. J'ai essayé d'étendre StringProtocol
sans succès, car la méthode index
n'existe pas là.
Swift 3:
extension String {
subscript (i: Int) -> Character {
return self[index(startIndex, offsetBy: i)]
}
subscript (i: Int) -> String {
return String(self[i] as Character)
}
subscript (r: Range<Int>) -> String {
let start = index(startIndex, offsetBy: r.lowerBound)
let end = index(startIndex, offsetBy: r.upperBound)
return self[Range(start ..< end)]
}
}
Pourquoi ce n'est pas intégré?
Apple fournit l'explication suivante (trouvés ici):
Chaînes D'inscription avec des entiers n'est pas disponible.
Le concept de "le
i
e caractère dans une chaîne" a différentes interprétations dans différentes bibliothèques et systèmes composant. L'interprétation correcte doit être sélectionné selon le cas d'utilisation et les API impliquées, doncString
ne peut pas être subscrit avec un entier.Swift offre plusieurs façons d'accéder au personnage données stockées dans les chaînes.
String.utf8
est une collection D'UTF-8 unités de code dans le chaîne. Utilisez cette API lors de la conversion de la chaîne en UTF-8. La plupart des API POSIX traitent des chaînes en termes D'unités de code UTF-8.
String.utf16
est une collection D'unités de code UTF-16 dans chaîne. La plupart des API Cocoa et Cocoa touch traitent les chaînes termes des unités de code UTF-16. Par exemple, en cas deNSRange
utilisé avecNSAttributedString
etNSRegularExpression
stocke les décalages et les longueurs de sous-chaîne dans termes des unités de code UTF-16.
String.unicodeScalars
est une collection de Scalaires Unicode. Utilisez cette API lorsque vous effectuez une manipulation de bas niveau des données de caractère.
String.characters
est une collection de l'étendue de graphème clusters, qui sont une approximation de l'utilisateur perçu caractère.Notez que lors du traitement de chaînes contenant du texte lisible par l'homme, le traitement caractère par caractère doit être évité dans la plus grande mesure possible. Utilisez plutôt des algorithmes Unicode sensibles aux paramètres régionaux, par exemple,
String.localizedStandardCompare()
,String.localizedLowercaseString
,String.localizedStandardRangeOfString()
etc.
Chaîne prend en charge indice (accès avec [ ] ) hors de la boîte:
Swift 4
let str = "Hello, world!"
let index = str.index(str.startIndex, offsetBy: 4)
str[index] // returns Character 'o'
let endIndex = str.index(str.endIndex, offsetBy:-2)
str[index ..< endIndex] // returns String "o, worl"
String(str.suffix(from: index)) // returns String "o, world!"
String(str.prefix(upTo: index)) // returns String "Hell"
En utilisant vos propres extensions, vous pouvez utiliser une syntaxe plus concise:
let str = "abcdef"
str[1 ..< 3] // returns "bc"
str[5] // returns "f"
str[80] // returns ""
str.substring(fromIndex: 3) // returns "def"
str.substring(toIndex: str.length - 2) // returns "abcd"
... votre extension de chaîne devrait être comme (entièrement testé):
extension String {
var length: Int {
return self.characters.count
}
subscript (i: Int) -> String {
return self[i ..< i + 1]
}
func substring(fromIndex: Int) -> String {
return self[min(fromIndex, length) ..< length]
}
func substring(toIndex: Int) -> String {
return self[0 ..< max(0, toIndex)]
}
subscript (r: Range<Int>) -> String {
let range = Range(uncheckedBounds: (lower: max(0, min(length, r.lowerBound)),
upper: min(length, max(0, r.upperBound))))
let start = index(startIndex, offsetBy: range.lowerBound)
let end = index(start, offsetBy: range.upperBound - range.lowerBound)
return String(self[start ..< end])
}
}
Pas d'indexation en utilisant des entiers, seulement en utilisant String.Index
. Surtout avec une complexité linéaire. Vous pouvez également créer des plages à partir de String.Index
et obtenir des sous-chaînes en les utilisant.
Swift 3.0
let firstChar = someString[someString.startIndex]
let lastChar = someString[someString.index(before: someString.endIndex)]
let charAtIndex = someString[someString.index(someString.startIndex, offsetBy: 10)]
let range = someString.startIndex..<someString.index(someString.startIndex, offsetBy: 10)
let substring = someString[range]
Swift 2.x
let firstChar = someString[someString.startIndex]
let lastChar = someString[someString.endIndex.predecessor()]
let charAtIndex = someString[someString.startIndex.advanceBy(10)]
let range = someString.startIndex..<someString.startIndex.advanceBy(10)
let subtring = someString[range]
Notez que vous ne pouvez jamais utiliser un index (ou une plage) créé d'une chaîne à une autre chaîne
let index10 = someString.startIndex.advanceBy(10)
//will compile
//sometimes it will work but sometimes it will crash or result in undefined behaviour
let charFromAnotherString = anotherString[index10]
Je viens de trouver cette solution de contournement soignée
var firstChar = Array(string)[0]
Swift 4.1 ou une version ultérieure
Vous pouvez étendre Stringprotocol de Swift 4 pour rendre l'indice disponible également aux sous-chaînes. Note:
En raison de la Proposition SE-0191 l'extension contrainte à IndexDistance == Int
peut être supprimée:
extension StringProtocol {
var string: String { return String(self) }
subscript(offset: Int) -> Element {
return self[index(startIndex, offsetBy: offset)]
}
subscript(_ range: CountableRange<Int>) -> SubSequence {
return prefix(range.lowerBound + range.count)
.suffix(range.count)
}
subscript(range: CountableClosedRange<Int>) -> SubSequence {
return prefix(range.lowerBound + range.count)
.suffix(range.count)
}
subscript(range: PartialRangeThrough<Int>) -> SubSequence {
return prefix(range.upperBound.advanced(by: 1))
}
subscript(range: PartialRangeUpTo<Int>) -> SubSequence {
return prefix(range.upperBound)
}
subscript(range: PartialRangeFrom<Int>) -> SubSequence {
return suffix(Swift.max(0, count - range.lowerBound))
}
}
extension Substring {
var string: String { return String(self) }
}
Test
let test = "Hello USA !!! Hello Brazil !!!"
test[safe: 10] // ""
test[11] // "!"
test[10...] // "!!! Hello Brazil !!!"
test[10..<12] // "!"
test[10...12] // "!!"
test[...10] // "Hello USA "
test[..<10] // "Hello USA "
test.first // "H"
test.last // "!"
// Subscripting the Substring
test[...][...3] // "Hell"
// Note that they all return a Substring of the original String.
// To create a new String you need to add .string as follow
test[10...].string // "!!! Hello Brazil !!!"
Swift 4
let str = "My String"
Chaîne à index
let index = str.index(str.startIndex, offsetBy: 3)
String(str[index]) // "S"
Sous-Chaîne
let startIndex = str.index(str.startIndex, offsetBy: 3)
let endIndex = str.index(str.startIndex, offsetBy: 7)
String(str[startIndex...endIndex]) // "Strin"
N Premiers caractères
let startIndex = str.index(str.startIndex, offsetBy: 3)
String(str[..<startIndex]) // "My "
N Derniers caractères
let startIndex = str.index(str.startIndex, offsetBy: 3)
String(str[startIndex...]) // "String"
Swift 2 et 3
str = "My String"
* * Chaîne À L'Index * *
Swift 2
let charAtIndex = String(str[str.startIndex.advancedBy(3)]) // charAtIndex = "S"
Swift 3
str[str.index(str.startIndex, offsetBy: 3)]
sous-Chaîne fromIndex toIndex
Swift 2
let subStr = str[str.startIndex.advancedBy(3)...str.startIndex.advancedBy(7)] // subStr = "Strin"
Swift 3
str[str.index(str.startIndex, offsetBy: 3)...str.index(str.startIndex, offsetBy: 7)]
Première n caractères
let first2Chars = String(str.characters.prefix(2)) // first2Chars = "My"
n Derniers caractères
let last3Chars = String(str.characters.suffix(3)) // last3Chars = "ing"
Swift 2.0 à partir de Xcode 7 GM Seed
var text = "Hello, world!"
let firstChar = text[text.startIndex.advancedBy(0)] // "H"
Pour le nième caractère, remplacez 0 par n-1.
Modifier: Swift 3.0
text[text.index(text.startIndex, offsetBy: 0)]
N. B. Il existe des moyens plus simples de saisir certains caractères dans la chaîne
Par exemple let firstChar = text.characters.first
Si vous voyez Cannot subscript a value of type 'String'...
utiliser cette extension:
Swift 3
extension String {
subscript (i: Int) -> Character {
return self[self.characters.index(self.startIndex, offsetBy: i)]
}
subscript (i: Int) -> String {
return String(self[i] as Character)
}
subscript (r: Range<Int>) -> String {
let start = index(startIndex, offsetBy: r.lowerBound)
let end = index(startIndex, offsetBy: r.upperBound)
return self[start..<end]
}
subscript (r: ClosedRange<Int>) -> String {
let start = index(startIndex, offsetBy: r.lowerBound)
let end = index(startIndex, offsetBy: r.upperBound)
return self[start...end]
}
}
Swift 2.3
extension String {
subscript(integerIndex: Int) -> Character {
let index = advance(startIndex, integerIndex)
return self[index]
}
subscript(integerRange: Range<Int>) -> String {
let start = advance(startIndex, integerRange.startIndex)
let end = advance(startIndex, integerRange.endIndex)
let range = start..<end
return self[range]
}
}
Solution Swift 2.2:
L'extension suivante fonctionne dans Xcode 7, c'est une combinaison de Cette solution et la conversion de syntaxe Swift 2.0.
extension String {
subscript(integerIndex: Int) -> Character {
let index = startIndex.advancedBy(integerIndex)
return self[index]
}
subscript(integerRange: Range<Int>) -> String {
let start = startIndex.advancedBy(integerRange.startIndex)
let end = startIndex.advancedBy(integerRange.endIndex)
let range = start..<end
return self[range]
}
}
La classe swift string ne permet pas d'obtenir un caractère à un index spécifique en raison de sa prise en charge native des caractères UTF. La longueur variable D'un caractère UTF en mémoire rend le saut directement à un caractère impossible. Cela signifie que vous devez faire une boucle manuellement sur la chaîne à chaque fois.
Vous pouvez étendre String pour fournir une méthode qui parcourra les caractères jusqu'à ce que votre index désiré
extension String {
func characterAtIndex(index: Int) -> Character? {
var cur = 0
for char in self {
if cur == index {
return char
}
cur++
}
return nil
}
}
myString.characterAtIndex(0)!
Comme note de côté, il y a quelques fonctions directement applicables à la représentation de la chaîne de caractères d'une chaîne, comme ceci:
var string = "Hello, playground"
let firstCharacter = string.characters.first // returns "H"
let lastCharacter = string.characters.last // returns "d"
Le résultat est de type Character, mais vous pouvez le convertir en chaîne.
Ou ceci:
let reversedString = String(string.characters.reverse())
// returns "dnuorgyalp ,olleH"
:-)
Swift 4
String(Array(stringToIndex)[index])
C'est probablement la meilleure façon de résoudre ce problème une fois. Vous voulez probablement lancer la chaîne en tant que tableau d'abord, puis lancer le résultat en tant que chaîne à nouveau. Sinon, un caractère sera renvoyé au lieu d'une chaîne.
Exemple {[1] } renverra "e" sous forme de chaîne.
(Array("HelloThere")[1]
retournera "e" en tant que personnage.
Swift ne permet pas aux chaînes d'être indexées comme des tableaux, mais cela fait le travail, style force brute.
J'ai juste eu le même problème. Faites simplement ceci:
var aString: String = "test"
var aChar:unichar = (aString as NSString).characterAtIndex(0)
Ma solution est dans une ligne, en supposant que cadena est la chaîne et 4 est la nième position que vous voulez:
let character = cadena[advance(cadena.startIndex, 4)]
Simple... Je suppose que Swift inclura plus de choses sur les sous-chaînes dans les futures versions.
Ma solution très simple:
let myString = "Test string"
let index = 0
let firstCharacter = myString[String.Index(encodedOffset: index)]
Afin d'alimenter le sujet et de montrer les possibilités d'indice swift, voici une petite chaîne "substring-toolbox" en indice
Ces méthodes sont sûres et ne passent jamais sur les index de chaînes
extension String {
// string[i] -> one string char
subscript(pos: Int) -> String { return String(Array(self)[min(self.length-1,max(0,pos))]) }
// string[pos,len] -> substring from pos for len chars on the left
subscript(pos: Int, len: Int) -> String { return self[pos, len, .pos_len, .left2right] }
// string[pos, len, .right2left] -> substring from pos for len chars on the right
subscript(pos: Int, len: Int, way: Way) -> String { return self[pos, len, .pos_len, way] }
// string[range] -> substring form start pos on the left to end pos on the right
subscript(range: Range<Int>) -> String { return self[range.startIndex, range.endIndex, .start_end, .left2right] }
// string[range, .right2left] -> substring start pos on the right to end pos on the left
subscript(range: Range<Int>, way: Way) -> String { return self[range.startIndex, range.endIndex, .start_end, way] }
var length: Int { return countElements(self) }
enum Mode { case pos_len, start_end }
enum Way { case left2right, right2left }
subscript(var val1: Int, var val2: Int, mode: Mode, way: Way) -> String {
if mode == .start_end {
if val1 > val2 { let val=val1 ; val1=val2 ; val2=val }
val2 = val2-val1
}
if way == .left2right {
val1 = min(self.length-1, max(0,val1))
val2 = min(self.length-val1, max(1,val2))
} else {
let val1_ = val1
val1 = min(self.length-1, max(0, self.length-val1_-val2 ))
val2 = max(1, (self.length-1-val1_)-(val1-1) )
}
return self.bridgeToObjectiveC().substringWithRange(NSMakeRange(val1, val2))
//-- Alternative code without bridge --
//var range: Range<Int> = pos...(pos+len-1)
//var start = advance(startIndex, range.startIndex)
//var end = advance(startIndex, range.endIndex)
//return self.substringWithRange(Range(start: start, end: end))
}
}
println("0123456789"[3]) // return "3"
println("0123456789"[3,2]) // return "34"
println("0123456789"[3,2,.right2left]) // return "56"
println("0123456789"[5,10,.pos_len,.left2right]) // return "56789"
println("0123456789"[8,120,.pos_len,.right2left]) // return "01"
println("0123456789"[120,120,.pos_len,.left2right]) // return "9"
println("0123456789"[0...4]) // return "01234"
println("0123456789"[0..4]) // return "0123"
println("0123456789"[0...4,.right2left]) // return "56789"
println("0123456789"[4...0,.right2left]) // return "678" << because ??? range can wear endIndex at 0 ???
Mise à jour pour la sous-chaîne swift 2.0
public extension String {
public subscript (i: Int) -> String {
return self.substringWithRange(self.startIndex..<self.startIndex.advancedBy(i + 1))
}
public subscript (r: Range<Int>) -> String {
get {
return self.substringWithRange(self.startIndex.advancedBy(r.startIndex)..<self.startIndex.advancedBy(r.endIndex))
}
}
}
Je pense qu'une réponse rapide pour obtenir le premier personnage pourrait être:
let firstCharacter = aString[aString.startIndex]
C'est tellement élégant et performant que:
let firstCharacter = Array(aString.characters).first
Mais.. si vous voulez manipuler et faire plus d'opérations avec des chaînes, vous pouvez penser à créer une extension..voici une extension avec cette approche, c'est assez similaire à celle déjà affichée ici:
extension String {
var length : Int {
return self.characters.count
}
subscript(integerIndex: Int) -> Character {
let index = startIndex.advancedBy(integerIndex)
return self[index]
}
subscript(integerRange: Range<Int>) -> String {
let start = startIndex.advancedBy(integerRange.startIndex)
let end = startIndex.advancedBy(integerRange.endIndex)
let range = start..<end
return self[range]
}
}
MAIS C'EST UNE IDÉE TERRIBLE!!
L'extension ci-dessous est horriblement inefficace. Chaque fois qu'une chaîne est accessible avec un entier, une fonction O(N) pour faire avancer son index de départ est exécutée. Exécuter une boucle linéaire dans une autre boucle linéaire signifie que cette boucle for Est accidentellement O (n2) - à mesure que la longueur de la chaîne augmente, le temps que prend cette boucle augmente quadratiquement.
Au lieu de faire cela, vous pouvez utiliser la collection de chaînes des caractères.
Dans Swift 3
let mystring = "Hello, world!"
let stringToArray = Array(mystring.characters)
let indices = (stringToArray.count)-1
print(stringToArray[0]) //H
print(stringToArray[indices]) //!
Swift 3: une autre solution (testé dans l'aire de jeux)
extension String {
func substr(_ start:Int, length:Int=0) -> String? {
guard start > -1 else {
return nil
}
let count = self.characters.count - 1
guard start <= count else {
return nil
}
let startOffset = max(0, start)
let endOffset = length > 0 ? min(count, startOffset + length - 1) : count
return self[self.index(self.startIndex, offsetBy: startOffset)...self.index(self.startIndex, offsetBy: endOffset)]
}
}
Utilisation:
let txt = "12345"
txt.substr(-1) //nil
txt.substr(0) //"12345"
txt.substr(0, length: 0) //"12345"
txt.substr(1) //"2345"
txt.substr(2) //"345"
txt.substr(3) //"45"
txt.substr(4) //"5"
txt.substr(6) //nil
txt.substr(0, length: 1) //"1"
txt.substr(1, length: 1) //"2"
txt.substr(2, length: 1) //"3"
txt.substr(3, length: 1) //"4"
txt.substr(3, length: 2) //"45"
txt.substr(3, length: 3) //"45"
txt.substr(4, length: 1) //"5"
txt.substr(4, length: 2) //"5"
txt.substr(5, length: 1) //nil
txt.substr(5, length: -1) //nil
txt.substr(-1, length: -1) //nil
Swift3
Vous pouvez utiliser la syntaxe d'indice pour accéder au caractère à un index de chaîne particulier.
let greeting = "Guten Tag!"
let index = greeting.index(greeting.startIndex, offsetBy: 7)
greeting[index] // a
Ou nous pouvons faire une Extension de chaîne dans Swift 4
extension String {
func getCharAtIndex(_ index: Int) -> Character {
return self[self.index(self.startIndex, offsetBy: index)]
}
}
Utilisation:
let foo = "ABC123"
foo.getCharAtIndex(2) //C
Swift 4
Plage et Plage partielle subscripting en utilisant String
'S indices
propriété
Comme variation de @leodabus belle réponse , nous pouvons ajouter une extension supplémentaire à DefaultBidirectionalIndices
dans le but de nous permettre de retomber sur la indices
propriété de String
lors de la mise en œuvre des indices personnalisés (par Int
plages spécialisées et plages partielles) pour ce dernier.
extension DefaultBidirectionalIndices {
subscript(at: Int) -> Elements.Index {
return index(startIndex, offsetBy: at)
}
}
// Moving the index(_:offsetBy:) to an extension yields slightly
// briefer implementations for these String extensions.
extension String {
subscript(r: CountableClosedRange<Int>) -> SubSequence {
return self[indices[r.lowerBound]...indices[r.upperBound]]
}
subscript(r: CountablePartialRangeFrom<Int>) -> SubSequence {
return self[indices[r.lowerBound]...]
}
subscript(r: PartialRangeThrough<Int>) -> SubSequence {
return self[...indices[r.upperBound]]
}
subscript(r: PartialRangeUpTo<Int>) -> SubSequence {
return self[..<indices[r.upperBound]]
}
}
let str = "foo bar baz bax"
print(str[4...6]) // "bar"
print(str[4...]) // "bar baz bax"
print(str[...6]) // "foo bar"
print(str[..<6]) // "foo ba"
Merci @LeoDabus de m'avoir pointé dans la direction de l'utilisation du indices
propriété comme une(autre) alternative à String
subscripting!
Swift 4.2.
Dans Swift 4.2, DefaultBidirectionalIndices
a été dépréciée en faveur de DefaultIndices
.
Le type String
de Swift ne fournit pas de méthode characterAtIndex
car il existe plusieurs façons d'encoder une chaîne Unicode. Allez - vous avec UTF8, UTF16, ou autre chose?
Vous pouvez accéder aux collections CodeUnit
en récupérant les propriétés String.utf8
et String.utf16
. Vous pouvez également accéder à la collection UnicodeScalar
en récupérant la propriété String.unicodeScalars
.
Dans l'esprit de l'implémentation de NSString
, je retourne un type unichar
.
extension String
{
func characterAtIndex(index:Int) -> unichar
{
return self.utf16[index]
}
// Allows us to use String[index] notation
subscript(index:Int) -> unichar
{
return characterAtIndex(index)
}
}
let text = "Hello Swift!"
let firstChar = text[0]
Une solution de type python, qui vous permet d'utiliser un index négatif,
var str = "Hello world!"
str[-1] // "!"
Pourrait être:
extension String {
subscript (var index:Int)->Character{
get {
let n = distance(self.startIndex, self.endIndex)
index %= n
if index < 0 { index += n }
return self[advance(startIndex, index)]
}
}
}
En passant, il peut être utile de transposer toute la notation de tranche de Python
Vous pouvez également convertir une chaîne en tableau de caractères comme ceci:
let text = "My Text"
let index = 2
let charSequence = text.unicodeScalars.map{ Character($0) }
let char = charSequence[index]
C'est le moyen d'obtenir char à l'index spécifié en temps constant.
L'exemple ci-dessous ne s'exécute pas en temps constant, mais nécessite un temps linéaire. Donc, si vous avez beaucoup de recherche dans String by index, utilisez la méthode ci-dessus.
let char = text[text.startIndex.advancedBy(index)]
Swift 3
extension String {
public func charAt(_ i: Int) -> Character {
return self[self.characters.index(self.startIndex, offsetBy: i)]
}
public subscript (i: Int) -> String {
return String(self.charAt(i) as Character)
}
public subscript (r: Range<Int>) -> String {
return substring(with: self.characters.index(self.startIndex, offsetBy: r.lowerBound)..<self.characters.index(self.startIndex, offsetBy: r.upperBound))
}
public subscript (r: CountableClosedRange<Int>) -> String {
return substring(with: self.characters.index(self.startIndex, offsetBy: r.lowerBound)..<self.characters.index(self.startIndex, offsetBy: r.upperBound))
}
}
L'Utilisation de
let str = "Hello World"
let sub = str[0...4]
Utiliser caractères pour faire le travail. Vous pouvez rapidement convertir la chaîne en un tableau de caractères pouvant être manipulés par les méthodes CharacterView.
Exemple:
let myString = "Hello World!"
let myChars = myString.characters
(full CharacterView doc)
(testé dans Swift 3)
Il y a une alternative, expliquée dans String manifesto
extension String : BidirectionalCollection {
subscript(i: Index) -> Character { return characters[i] }
}
Obtenir la première lettre:
first(str) // retrieve first letter
Plus ici: http://sketchytech.blogspot.com/2014/08/swift-pure-swift-method-for-returning.html
Get & Set Indice (String & Substring) - Swift 4.1
Swift 4.1, Xcode 9.3
J'ai basé ma réponse sur la réponse de @alecarlson.
La seule grande différence est , vous pouvez obtenir un Substring
ou String
retourné (et, dans certains cas, un seul Character
). Vous pouvez aussi get
et set
l'indice.
Enfin, le mien est plus lourd et plus long que @alecarlson et en tant que tel, je vous suggère de le mettre dans un fichier source.
Extension:
public extension String {
public subscript (i: Int) -> Character {
get {
return self[index(startIndex, offsetBy: i)]
}
set (c) {
let n = index(startIndex, offsetBy: i)
replaceSubrange(n...n, with: "\(c)")
}
}
public subscript (bounds: CountableRange<Int>) -> Substring {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[start ..< end]
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(start ..< end, with: s)
}
}
public subscript (bounds: CountableClosedRange<Int>) -> Substring {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[start ... end]
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(start ... end, with: s)
}
}
public subscript (bounds: CountablePartialRangeFrom<Int>) -> Substring {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(endIndex, offsetBy: -1)
return self[start ... end]
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(endIndex, offsetBy: -1)
replaceSubrange(start ... end, with: s)
}
}
public subscript (bounds: PartialRangeThrough<Int>) -> Substring {
get {
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[startIndex ... end]
}
set (s) {
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(startIndex ... end, with: s)
}
}
public subscript (bounds: PartialRangeUpTo<Int>) -> Substring {
get {
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[startIndex ..< end]
}
set (s) {
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(startIndex ..< end, with: s)
}
}
public subscript (i: Int) -> String {
get {
return "\(self[index(startIndex, offsetBy: i)])"
}
set (c) {
let n = index(startIndex, offsetBy: i)
self.replaceSubrange(n...n, with: "\(c)")
}
}
public subscript (bounds: CountableRange<Int>) -> String {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return "\(self[start ..< end])"
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(start ..< end, with: s)
}
}
public subscript (bounds: CountableClosedRange<Int>) -> String {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return "\(self[start ... end])"
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(start ... end, with: s)
}
}
public subscript (bounds: CountablePartialRangeFrom<Int>) -> String {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(endIndex, offsetBy: -1)
return "\(self[start ... end])"
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(endIndex, offsetBy: -1)
replaceSubrange(start ... end, with: s)
}
}
public subscript (bounds: PartialRangeThrough<Int>) -> String {
get {
let end = index(startIndex, offsetBy: bounds.upperBound)
return "\(self[startIndex ... end])"
}
set (s) {
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(startIndex ... end, with: s)
}
}
public subscript (bounds: PartialRangeUpTo<Int>) -> String {
get {
let end = index(startIndex, offsetBy: bounds.upperBound)
return "\(self[startIndex ..< end])"
}
set (s) {
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(startIndex ..< end, with: s)
}
}
public subscript (i: Int) -> Substring {
get {
return Substring("\(self[index(startIndex, offsetBy: i)])")
}
set (c) {
let n = index(startIndex, offsetBy: i)
replaceSubrange(n...n, with: "\(c)")
}
}
}
public extension Substring {
public subscript (i: Int) -> Character {
get {
return self[index(startIndex, offsetBy: i)]
}
set (c) {
let n = index(startIndex, offsetBy: i)
replaceSubrange(n...n, with: "\(c)")
}
}
public subscript (bounds: CountableRange<Int>) -> Substring {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[start ..< end]
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(start ..< end, with: s)
}
}
public subscript (bounds: CountableClosedRange<Int>) -> Substring {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[start ... end]
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(start ... end, with: s)
}
}
public subscript (bounds: CountablePartialRangeFrom<Int>) -> Substring {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(endIndex, offsetBy: -1)
return self[start ... end]
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(endIndex, offsetBy: -1)
replaceSubrange(start ... end, with: s)
}
}
public subscript (bounds: PartialRangeThrough<Int>) -> Substring {
get {
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[startIndex ... end]
}
set (s) {
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(startIndex ..< end, with: s)
}
}
public subscript (bounds: PartialRangeUpTo<Int>) -> Substring {
get {
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[startIndex ..< end]
}
set (s) {
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(startIndex ..< end, with: s)
}
}
public subscript (i: Int) -> String {
get {
return "\(self[index(startIndex, offsetBy: i)])"
}
set (c) {
let n = index(startIndex, offsetBy: i)
replaceSubrange(n...n, with: "\(c)")
}
}
public subscript (bounds: CountableRange<Int>) -> String {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return "\(self[start ..< end])"
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(start ..< end, with: s)
}
}
public subscript (bounds: CountableClosedRange<Int>) -> String {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return "\(self[start ... end])"
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(start ... end, with: s)
}
}
public subscript (bounds: CountablePartialRangeFrom<Int>) -> String {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(endIndex, offsetBy: -1)
return "\(self[start ... end])"
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(endIndex, offsetBy: -1)
replaceSubrange(start ... end, with: s)
}
}
public subscript (bounds: PartialRangeThrough<Int>) -> String {
get {
let end = index(startIndex, offsetBy: bounds.upperBound)
return "\(self[startIndex ... end])"
}
set (s) {
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(startIndex ... end, with: s)
}
}
public subscript (bounds: PartialRangeUpTo<Int>) -> String {
get {
let end = index(startIndex, offsetBy: bounds.upperBound)
return "\(self[startIndex ..< end])"
}
set (s) {
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(startIndex ..< end, with: s)
}
}
public subscript (i: Int) -> Substring {
get {
return Substring("\(self[index(startIndex, offsetBy: i)])")
}
set (c) {
let n = index(startIndex, offsetBy: i)
replaceSubrange(n...n, with: "\(c)")
}
}
}