Je n'ai pas encore pu comprendre comment obtenir une sous-chaîne d'un String
dans Swift:
var str = “Hello, playground”
func test(str: String) -> String {
return str.substringWithRange( /* What goes here? */ )
}
test (str)
Je ne suis pas en mesure de créer une gamme dans Swift. La saisie semi-automatique dans Playground n'est pas très utile - c'est ce qu'elle suggère:
return str.substringWithRange(aRange: Range<String.Index>)
Je n'ai rien trouvé dans la bibliothèque de référence standard Swift qui aide. Voici une autre supposition sauvage:
return str.substringWithRange(Range(0, 1))
Et ça:
let r:Range<String.Index> = Range<String.Index>(start: 0, end: 2)
return str.substringWithRange(r)
J'ai vu d'autres réponses ( trouver l'index de caractère dans la chaîne Swift ) qui semblent suggérer que puisqu'il String
s'agit d'un type de pont pour NSString
, les "anciennes" méthodes devraient fonctionner, mais il n'est pas clair comment - par exemple, cela ne fonctionne pas non plus ( ne semble pas être une syntaxe valide):
let x = str.substringWithRange(NSMakeRange(0, 3))
Pensées?
Réponses:
Vous pouvez utiliser la méthode substringWithRange. Il faut un début et une fin String.Index.
Pour modifier l'index de début et de fin, utilisez advancedBy (n).
Vous pouvez également utiliser la méthode NSString avec NSRange, mais vous devez vous assurer que vous utilisez une NSString comme celle-ci:
Remarque: comme JanX2 l'a mentionné, cette deuxième méthode n'est pas sûre avec les chaînes unicode.
la source
advance
signifie que nous devons parcourir tout le chemin à travers une chaîne éventuellement longue. Mais former un NSRange et utiliser NSString explicitement est dangereux? Ce qui reste?Swift 2
Facile
Swift 3
Swift 4
substring(to:)
etsubstring(from:)
sont obsolètesSwift 4
.la source
REMARQUE: @airspeedswift fait quelques points très perspicaces sur les compromis de cette approche, en particulier les impacts cachés sur les performances. Les chaînes ne sont pas de simples bêtes, et atteindre un index particulier peut prendre du temps O (n), ce qui signifie qu'une boucle qui utilise un indice peut être O (n ^ 2). Tu étais prévenu.
Vous avez juste besoin d'ajouter une nouvelle
subscript
fonction qui prend une plage et utiliseadvancedBy()
pour marcher où vous voulez:(Cela devrait certainement faire partie de la langue. Dupe rdar: // 17158813 )Pour le plaisir, vous pouvez également ajouter un
+
opérateur sur les index:(Je ne sais pas encore si celui-ci devrait faire partie de la langue ou non.)
la source
advance<T>(…)
dans l'Swift
espace de noms.String.Index
. Dans ce cas, il ne s'agit pas autant d'optimisation que de tout garder simple. Devoir jongler entre int et String.Index aller-retour partout mènera à un gâchis.String.Index
es), ce qui est souvent le cas. Alors vous pouvez simplement souhaiter que toutes ces méthodes de manipulation de chaînes fonctionnent avecInt
s. Et vous êtes obligé de le convertir, ceString.Indexes
qui conduit au désordre que vous avez mentionné.Au moment où j'écris, aucune extension n'est parfaitement compatible avec Swift 4.2 , alors voici une qui couvre tous les besoins auxquels je pourrais penser:
Et puis, vous pouvez utiliser:
string.substring(from: 1, to: 7)
vous obtient:ello,Wo
string.substring(to: 7)
vous obtient:Hello,Wo
string.substring(from: 3)
vous obtient:lo,World!
string.substring(from: 1, length: 4)
vous obtient:ello
string.substring(length: 4, to: 7)
vous obtient:o,Wo
Mis
substring(from: Int?, length: Int)
à jour pour prendre en charge à partir de zéro.la source
"Hello😇😍😘😎📸📀💾∝ℵℶ≹".substring(from: 4, to: 14)
nous donne:o😇😍😘😎📸📀💾∝ℵℶ
SWIFT 2.0
Facile:
SWIFT 3.0
SWIFT 4.0
Les opérations de sous-chaîne retournent une instance du type Substring, au lieu de String.
la source
text[text.startIndex..<text.index(text.startIndex, offsetBy: 2)]
C'est beaucoup plus simple que n'importe laquelle des réponses ici, une fois que vous avez trouvé la bonne syntaxe.
Je veux enlever le [et]
le résultat sera "ABCDEFGHI", le startIndex et le endIndex pourraient également être utilisés dans
etc!
PS: Comme indiqué dans les remarques, il y a quelques changements de syntaxe dans swift 2 qui vient avec xcode 7 et iOS9!
Veuillez regarder cette page
la source
advance(myString.endIndex, -1)
syntaxe Xcode 7 beta 6 a changé enmyString.endIndex.advancedBy(-1)
Par exemple pour trouver le prénom (jusqu'au premier espace) dans mon nom complet:
start
etend
sont de typeString.Index
ici et sont utilisés pour créer unRange<String.Index>
et utilisé dans l'accesseur d'indice (si un espace est trouvé dans la chaîne d'origine).Il est difficile de créer un
String.Index
directement à partir d'une position entière utilisée dans le message d'ouverture. En effet, en mon nom, chaque caractère aurait la même taille en octets. Mais les caractères utilisant des accents spéciaux dans d'autres langues auraient pu utiliser plusieurs octets supplémentaires (selon l'encodage utilisé). Alors, à quel octet doit se référer l'entier?Il est possible de créer un nouveau à
String.Index
partir d'un existant en utilisant les méthodessucc
etpred
qui s'assurera que le nombre correct d'octets est ignoré pour passer au point de code suivant dans l'encodage. Cependant, dans ce cas, il est plus facile de rechercher l'index du premier espace dans la chaîne pour trouver l'index de fin.la source
Pour moi, c'est la partie vraiment intéressante de votre question. Chaîne est ponté à NSString, donc la plupart des méthodes NSString faire le travail directement sur une chaîne. Vous pouvez les utiliser librement et sans réfléchir. Ainsi, par exemple, cela fonctionne exactement comme vous vous y attendez:
Mais, comme cela arrive souvent, "J'ai fait travailler mon mojo, mais ça ne marche pas pour vous." Vous venez de choisir l'un des rares cas où une méthode Swift parallèle portant le même nom existe , et dans un cas comme celui-ci, la méthode Swift éclipse la méthode Objective-C. Ainsi, lorsque vous dites
str.substringWithRange
, Swift pense que vous voulez dire la méthode Swift plutôt que la méthode NSString - et puis vous êtes arrosé, car la méthode Swift attend unRange<String.Index>
, et vous ne savez pas comment en faire un.Le moyen le plus simple est d'empêcher Swift de faire de l'ombre comme ça, en lançant explicitement:
Notez qu'aucun travail supplémentaire important n'est impliqué ici. "Cast" ne signifie pas "convertir"; la chaîne est en fait une chaîne NSString. Nous disons simplement à Swift à quoi ressembler cette variable pour les besoins de cette seule ligne de code.
La partie vraiment bizarre de tout cela est que la méthode Swift, qui cause tous ces problèmes, n'est pas documentée. Je n'ai aucune idée où il est défini; ce n'est pas dans l'en-tête NSString et ce n'est pas non plus dans l'en-tête Swift.
la source
Range<String.Index>
, soit éliminer cette méthode non documentée.Dans la nouvelle utilisation de Xcode 7.0
la source
.advancedBy(0)
n'est pas nécessaire pour startIndex.La réponse courte est que c'est vraiment difficile en Swift en ce moment. Mon intuition est qu'il y a encore beaucoup de travail à faire par Apple sur les méthodes pratiques pour des choses comme ça.
String.substringWithRange()
attend unRange<String.Index>
paramètre, et pour autant que je sache, il n'y a pas de méthode de générateur pour leString.Index
type. Vous pouvez récupérer desString.Index
valeurs deaString.startIndex
etaString.endIndex
et appeler.succ()
ou.pred()
sur eux, mais c'est de la folie.Que diriez-vous d'une extension sur la classe String qui prend de bons vieux
Int
s?Mise à jour: Swift beta 4 résout les problèmes ci-dessous!
En l'état [dans la version bêta 3 et antérieure], même les chaînes natives de Swift ont des problèmes avec la gestion des caractères Unicode. L'icône de chien ci-dessus a fonctionné, mais ce qui suit ne fonctionne pas:
Production:
la source
NSString
m'a fait penser que j'utilisais uniquement desString
méthodes natives de Swift , car je n'utilisais aucunmyString as NSString
appel.Vous pouvez utiliser ces extensions pour améliorer
substringWithRange
Swift 2.3
Swift 3
Usage:
la source
Exemple de code pour savoir comment obtenir une sous-chaîne dans Swift 2.0
(i) Sous-chaîne de l'index de départ
Contribution:-
Production:-
(ii) Sous-chaîne d'un index particulier
Contribution:-
Production:-
J'espère que cela vous aidera!
la source
Solution facile avec peu de code.
Faites une extension qui inclut une sous-chaîne de base que presque toutes les autres langues ont:
Appelez simplement cela avec
la source
Cela fonctionne dans mon terrain de jeu :)
la source
advance
Mis à jour pour Xcode 7. Ajoute l'extension de chaîne:
Utilisation:
La mise en oeuvre:
la source
essayez ceci dans la cour de récréation
ça vous donnera "bonjour, p"
Cependant, lorsque cela devient vraiment intéressant, c'est que si vous rendez le dernier index plus grand que la chaîne dans l'aire de jeux, il affichera toutes les chaînes que vous avez définies après str: o
Range () semble être une fonction générique de sorte qu'il doit connaître le type avec lequel il traite.
Vous devez également lui donner la chaîne réelle qui vous intéresse dans les aires de jeux car elle semble contenir toutes les piqûres l'une après l'autre avec leur nom de variable par la suite.
Alors
donne "bonjour, terrain de jeu str Je suis la chaîne suivante str2 "
fonctionne même si str2 est défini avec un let
:)
la source
Rob Napier avait déjà donné une réponse impressionnante en utilisant l'indice. Mais j'ai ressenti un inconvénient car il n'y a pas de vérification des conditions hors limite. Cela peut avoir tendance à planter. J'ai donc modifié l'extension et la voici
Sortie ci-dessous
Je suggère donc de toujours vérifier si laisser
la source
Dans Swift3
Par exemple: une variable "Duke James Thomas", nous devons obtenir "James".
la source
En prenant une page de Rob Napier, j'ai développé ces extensions de chaîne communes , dont deux sont:
Usage:
la source
Range
place deRange<String.Index>
grâce à l'inférence de type.Voici comment vous obtenez une plage d'une chaîne:
Le point clé est que vous passez une plage de valeurs de type String.Index (c'est ce que retourne l'avance) au lieu d'entiers.
La raison pour laquelle cela est nécessaire, c'est que les chaînes dans Swift n'ont pas d'accès aléatoire (en raison de la longueur variable des caractères Unicode essentiellement). Vous ne pouvez pas non plus le faire
str[1]
. String.Index est conçu pour fonctionner avec leur structure interne.Vous pouvez cependant créer une extension avec un indice, qui le fait pour vous, vous pouvez donc simplement passer une plage d'entiers (voir par exemple la réponse de Rob Napier ).
la source
J'ai essayé de trouver quelque chose de pythonique.
Tous les indices ici sont excellents, mais les fois où j'ai vraiment besoin de quelque chose de simple, c'est généralement quand je veux compter à l'envers, par exemple
string.endIndex.advancedBy(-1)
Il prend en charge les
nil
valeurs, pour l'index de début et de fin, oùnil
signifierait un index à 0 pour le début,string.characters.count
pour la fin.ÉDITER
Une solution plus élégante:
la source
Créez d'abord la plage, puis la sous-chaîne. Vous pouvez utiliser la
fromIndex..<toIndex
syntaxe comme ceci:la source
voici un exemple pour obtenir l'ID vidéo uniquement .ie (6oL687G0Iso) à partir de l'URL entière dans swift
la source
Échantillon complet que vous pouvez voir ici
la source
http://www.learnswiftonline.com/reference-guides/string-reference-guide-for-swift/ montre que cela fonctionne bien:
la source
Eh bien, j'ai eu le même problème et résolu avec la fonction "bridgeToObjectiveC ()":
Veuillez noter que dans l'exemple, substringWithRange en conjonction avec NSMakeRange prend la partie de la chaîne commençant à l'index 6 (caractère "W") et se terminant à l'index 6 + 6 positions en avant (caractère "!")
À votre santé.
la source
Vous pouvez utiliser n'importe laquelle des méthodes de sous-chaîne dans une extension Swift String que j'ai écrite https://bit.ly/JString .
la source
Si vous en avez un
NSRange
, le pontageNSString
fonctionne parfaitement. Par exemple, je travaillais avecUITextFieldDelegate
et je voulais rapidement calculer la nouvelle valeur de chaîne lorsqu'il m'a demandé s'il devait remplacer la plage.la source
Extension simple pour
String
:la source
Si vous ne vous souciez pas des performances ... c'est probablement la solution la plus concise de Swift 4
Cela vous permet de faire quelque chose comme ceci:
la source