Je souhaite convertir l'index d'une lettre contenue dans une chaîne en une valeur entière. Tentative de lecture des fichiers d'en-tête mais je ne trouve pas le type pour Index
, bien qu'il semble conforme au protocole ForwardIndexType
avec des méthodes (par exemple distanceTo
).
var letters = "abcdefg"
let index = letters.characters.indexOf("c")!
// ERROR: Cannot invoke initializer for type 'Int' with an argument list of type '(String.CharacterView.Index)'
let intValue = Int(index) // I want the integer value of the index (e.g. 2)
Toute aide est appréciée.
let index = letters.characters.index(of: "c")
Next Linelet int_index = letters.characters.distance(from: letters.startIndex, to: index)
Réponses:
modifier / mettre à jour:
Xcode 11 • Swift 5.1 ou version ultérieure
extension StringProtocol { func distance(of element: Element) -> Int? { firstIndex(of: element)?.distance(in: self) } func distance<S: StringProtocol>(of string: S) -> Int? { range(of: string)?.lowerBound.distance(in: self) } }
extension Collection { func distance(to index: Index) -> Int { distance(from: startIndex, to: index) } }
extension String.Index { func distance<S: StringProtocol>(in string: S) -> Int { string.distance(to: self) } }
Test de terrain de jeu
let letters = "abcdefg" let char: Character = "c" if let distance = letters.distance(of: char) { print("character \(char) was found at position #\(distance)") // "character c was found at position #2\n" } else { print("character \(char) was not found") }
let string = "cde" if let distance = letters.distance(of: string) { print("string \(string) was found at position #\(distance)") // "string cde was found at position #2\n" } else { print("string \(string) was not found") }
la source
Swift 4
var str = "abcdefg" let index = str.index(of: "c")?.encodedOffset // Result: 2
Remarque: si String contient les mêmes caractères multiples, il obtiendra simplement le plus proche de la gauche
var str = "abcdefgc" let index = str.index(of: "c")?.encodedOffset // Result: 2
la source
"🇺🇸🇺🇸🇧🇷".index(of: "🇧🇷")?.encodedOffset // 16
encodedOffset
est obsolète depuis Swift 4.2 .Message d'abandon:
encodedOffset
est obsolète car l'utilisation la plus courante est incorrecte. Utilisezutf16Offset(in:)
pour obtenir le même comportement.Nous pouvons donc utiliser
utf16Offset(in:)
comme ceci:var str = "abcdefgc" let index = str.index(of: "c")?.utf16Offset(in: str) // Result: 2
la source
let str = "🇺🇸🇺🇸🇧🇷"
let index = str.firstIndex(of: "🇧🇷")?.utf16Offset(in: str)
// Résultat: 8Pour effectuer une opération de chaîne basée sur un index, vous ne pouvez pas le faire avec l'approche numérique traditionnelle d'index. car swift.index est récupéré par la fonction index et n'est pas de type Int. Même si String est un tableau de caractères, nous ne pouvons toujours pas lire élément par index.
C'est frustrant.
Donc, pour créer une nouvelle sous-chaîne de chaque caractère pair de chaîne, vérifiez le code ci-dessous.
let mystr = "abcdefghijklmnopqrstuvwxyz" let mystrArray = Array(mystr) let strLength = mystrArray.count var resultStrArray : [Character] = [] var i = 0 while i < strLength { if i % 2 == 0 { resultStrArray.append(mystrArray[i]) } i += 1 } let resultString = String(resultStrArray) print(resultString)
Sortie: acegikmoqsuwy
Merci d'avance
la source
var counter = 0
let result = mystr.filter { _ in
defer { counter += 1 }
return counter.isMultiple(of: 2)
}
var index = mystr.startIndex
let result = mystr.filter { _ in
defer { mystr.formIndex(after: &index) }
return mystr.distance(from: mystr.startIndex, to: index).isMultiple(of: 2)
}
Voici une extension qui vous permettra d'accéder aux limites d'une sous-chaîne en tant que
Int
s au lieu deString.Index
valeurs:import Foundation /// This extension is available at /// https://gist.github.com/zackdotcomputer/9d83f4d48af7127cd0bea427b4d6d61b extension StringProtocol { /// Access the range of the search string as integer indices /// in the rendered string. /// - NOTE: This is "unsafe" because it may not return what you expect if /// your string contains single symbols formed from multiple scalars. /// - Returns: A `CountableRange<Int>` that will align with the Swift String.Index /// from the result of the standard function range(of:). func countableRange<SearchType: StringProtocol>( of search: SearchType, options: String.CompareOptions = [], range: Range<String.Index>? = nil, locale: Locale? = nil ) -> CountableRange<Int>? { guard let trueRange = self.range(of: search, options: options, range: range, locale: locale) else { return nil } let intStart = self.distance(from: startIndex, to: trueRange.lowerBound) let intEnd = self.distance(from: trueRange.lowerBound, to: trueRange.upperBound) + intStart return Range(uncheckedBounds: (lower: intStart, upper: intEnd)) } }
Sachez simplement que cela peut conduire à l'étrangeté, c'est pourquoi Apple a choisi de rendre les choses difficiles. (Bien que ce soit une décision de conception discutable - cacher une chose dangereuse en la rendant juste difficile ...)
Vous pouvez en lire plus dans la documentation String d'Apple , mais le tldr est qu'il provient du fait que ces "indices" sont en fait spécifiques à l'implémentation. Ils représentent les indices dans la chaîne après son rendu par le système d'exploitation et peuvent donc passer d'un système d'exploitation à un autre en fonction de la version de la spécification Unicode utilisée. Cela signifie que l'accès aux valeurs par index n'est plus une opération à temps constant, car la spécification UTF doit être exécutée sur les données pour déterminer le bon endroit dans la chaîne. Ces indices ne s'aligneront pas non plus avec les valeurs générées par NSString, si vous y faites un pont, ou avec les indices dans les scalaires UTF sous-jacents. Développeur de mise en garde.
la source
func rangeInt<S: StringProtocol>(of aString: S, options: String.CompareOptions = []) -> Range<Int>? {
guard let range = range(of: aString, options: options) else { return nil }
let start = distance(from: startIndex, to: range.lowerBound)
return start..<start+distance(from: range.lowerBound, to: range.upperBound)
}
countableRange
et reviendraisCountableRange