Quiero convertir el índice de una letra contenida dentro de una cadena en un valor entero. Intenté leer los archivos de encabezado pero no puedo encontrar el tipo Index
, aunque parece cumplir con el protocolo ForwardIndexType
con los métodos (por ejemplo 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)
Se agradece cualquier ayuda.
let index = letters.characters.index(of: "c")
next Linelet int_index = letters.characters.distance(from: letters.startIndex, to: index)
Respuestas:
editar / actualizar:
Xcode 11 • Swift 5.1 o posterior
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) } }
Prueba de patio de recreo
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") }
fuente
Rápido 4
var str = "abcdefg" let index = str.index(of: "c")?.encodedOffset // Result: 2
Nota: Si String contiene los mismos caracteres múltiples, solo obtendrá el más cercano desde la izquierda
var str = "abcdefgc" let index = str.index(of: "c")?.encodedOffset // Result: 2
fuente
"🇺🇸🇺🇸🇧🇷".index(of: "🇧🇷")?.encodedOffset // 16
encodedOffset
ha quedado obsoleto de Swift 4.2 .Mensaje de obsolescencia:
encodedOffset
ha quedado obsoleto porque el uso más común es incorrecto. Úseloutf16Offset(in:)
para lograr el mismo comportamiento.Entonces podemos usar
utf16Offset(in:)
así:var str = "abcdefgc" let index = str.index(of: "c")?.utf16Offset(in: str) // Result: 2
fuente
let str = "🇺🇸🇺🇸🇧🇷"
let index = str.firstIndex(of: "🇧🇷")?.utf16Offset(in: str)
// Resultado: 8Para realizar una operación de cadena basada en el índice, no puede hacerlo con el enfoque numérico de índice tradicional. porque swift.index es recuperado por la función de índices y no está en el tipo Int. Aunque String es una matriz de caracteres, no podemos leer elemento por índice.
Esto es frustrante.
Entonces, para crear una nueva subcadena de cada carácter par de la cadena, verifique el código a continuación.
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)
Salida: acegikmoqsuwy
Gracias por adelantado
fuente
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)
}
Aquí hay una extensión que le permitirá acceder a los límites de una subcadena como
Int
s en lugar deString.Index
valores: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)) } }
Solo tenga en cuenta que esto puede generar rarezas, razón por la cual Apple ha optado por hacerlo difícil. (Aunque esa es una decisión de diseño discutible: ocultar algo peligroso simplemente haciéndolo difícil ...)
Puede leer más en la documentación de String de Apple , pero el tldr es que se deriva del hecho de que estos "índices" son en realidad específicos de la implementación. Representan los índices en la cadena después de que el sistema operativo la haya representado, por lo que pueden cambiar de un sistema operativo a otro según la versión de la especificación Unicode que se esté utilizando. Esto significa que acceder a los valores por índice ya no es una operación de tiempo constante, porque la especificación UTF debe ejecutarse sobre los datos para determinar el lugar correcto en la cadena. Estos índices tampoco se alinearán con los valores generados por NSString, si se conecta a él, o con los índices en los escalares UTF subyacentes. Desarrollador de advertencia.
fuente
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
CountableRange