Todavía no he podido descubrir cómo obtener una subcadena de a String
en Swift:
var str = “Hello, playground”
func test(str: String) -> String {
return str.substringWithRange( /* What goes here? */ )
}
test (str)
No puedo crear un Rango en Swift. Autocompletar en el área de juegos no es muy útil: esto es lo que sugiere:
return str.substringWithRange(aRange: Range<String.Index>)
No he encontrado nada en la Biblioteca de referencia estándar de Swift que me ayude. Aquí había otra conjetura salvaje:
return str.substringWithRange(Range(0, 1))
Y esto:
let r:Range<String.Index> = Range<String.Index>(start: 0, end: 2)
return str.substringWithRange(r)
He visto otras respuestas ( Búsqueda de índice de caracteres en Swift String ) que parecen sugerir que, dado que String
es un tipo de puente NSString
, los métodos "antiguos" deberían funcionar, pero no está claro cómo, por ejemplo, esto tampoco funciona ( no parece ser una sintaxis válida):
let x = str.substringWithRange(NSMakeRange(0, 3))
Pensamientos?
Respuestas:
Puede usar el método substringWithRange. Se necesita un inicio y fin de String.Index.
Para cambiar el índice inicial y final, use advancedBy (n).
También puede seguir utilizando el método NSString con NSRange, pero debe asegurarse de utilizar un NSString como este:
Nota: como se menciona en JanX2, este segundo método no es seguro con cadenas unicode.
fuente
advance
significa que tenemos que recorrer todo el camino a través de una cadena posiblemente larga. ¿Pero formar un NSRange y usar NSString explícitamente es peligroso? ¿Lo que queda?Swift 2
Sencillo
Swift 3
Swift 4
substring(to:)
ysubstring(from:)
están en desuso enSwift 4
.fuente
NOTA: @airspeedswift hace algunos puntos muy perspicaces sobre las compensaciones de este enfoque, particularmente los impactos ocultos en el rendimiento. Las cadenas no son simples bestias, y llegar a un índice particular puede llevar tiempo O (n), lo que significa que un bucle que usa un subíndice puede ser O (n ^ 2). Usted ha sido advertido.
Solo necesita agregar una nueva
subscript
función que tome un rango y useadvancedBy()
para caminar hacia donde desee:(Esto definitivamente debería ser parte del lenguaje. Por favor engañe rdar: // 17158813 )Por diversión, también puede agregar un
+
operador a los índices:(Todavía no sé si este debería ser parte del lenguaje o no).
fuente
advance<T>(…)
en elSwift
espacio de nombres.String.Index
. En este caso, no es tanta optimización como mantener todo directo. Tener que hacer malabarismos entre int y String. El índice de ida y vuelta en todas partes conducirá a un desastre.String.Index
es), lo que suele ser el caso. De lo que puede desear, todos esos métodos de manejo de cadenas estaban trabajando conInt
s. Y se ve obligado a convertirlo, loString.Indexes
que conduce al desastre que mencionó.En el momento en que escribo, ninguna extensión es perfectamente compatible con Swift 4.2 , así que aquí hay una que cubre todas las necesidades que se me ocurren:
Y luego, puedes usar:
string.substring(from: 1, to: 7)
te consigue:ello,Wo
string.substring(to: 7)
te consigue:Hello,Wo
string.substring(from: 3)
te consigue:lo,World!
string.substring(from: 1, length: 4)
te consigue:ello
string.substring(length: 4, to: 7)
te consigue:o,Wo
Actualizado
substring(from: Int?, length: Int)
para admitir a partir de cero.fuente
"Hello😇😍😘😎📸📀💾∝ℵℶ≹".substring(from: 4, to: 14)
nos da:o😇😍😘😎📸📀💾∝ℵℶ
SWIFT 2.0
sencillo:
SWIFT 3.0
SWIFT 4.0
Las operaciones de subcadena devuelven una instancia del tipo Substring, en lugar de String.
fuente
text[text.startIndex..<text.index(text.startIndex, offsetBy: 2)]
Es mucho más simple que cualquiera de las respuestas aquí, una vez que encuentre la sintaxis correcta.
Quiero quitarme el [y]
el resultado será "ABCDEFGHI", el startIndex y endIndex también podrían usarse
¡y así!
PD: Como se indica en los comentarios, ¡hay algunos cambios de sintaxis en swift 2 que viene con xcode 7 y iOS9!
Por favor mira esta página
fuente
advance(myString.endIndex, -1)
sintaxis de Xcode 7 beta 6 ha cambiado amyString.endIndex.advancedBy(-1)
Por ejemplo, para encontrar el primer nombre (hasta el primer espacio) en mi nombre completo:
start
yend
son de tipoString.Index
aquí y se usan para crear ay seRange<String.Index>
usan en el descriptor de acceso de subíndice (si se encuentra un espacio en la cadena original).Es difícil crear un
String.Index
directamente desde una posición entera como se usa en la publicación de apertura. Esto se debe a que, en mi nombre, cada carácter tendría el mismo tamaño en bytes. Pero los caracteres que usan acentos especiales en otros idiomas podrían haber usado varios bytes más (dependiendo de la codificación utilizada). Entonces, ¿a qué byte debería referirse el entero?Es posible crear uno nuevo a
String.Index
partir de uno existente usando los métodossucc
ypred
que asegurará que se omita el número correcto de bytes para llegar al siguiente punto de código en la codificación. Sin embargo, en este caso, es más fácil buscar el índice del primer espacio en la cadena para encontrar el índice final.fuente
Para mí, esa es la parte realmente interesante de tu pregunta. Cadena está puenteado a NSString, por lo que la mayor parte métodos NSString hacen el trabajo directamente en una cadena. Puedes usarlos libremente y sin pensar. Entonces, por ejemplo, esto funciona tal como espera:
Pero, como suele suceder, "conseguí que mi mojo funcionara pero simplemente no funciona en ti". Simplemente elegiste uno de los raros casos en los que existe un método Swift paralelo idénticamente llamado , y en un caso como ese, el método Swift eclipsa el método Objective-C. Por lo tanto, cuando dices
str.substringWithRange
, Swift cree que te refieres al método Swift en lugar del método NSString, y luego te mandan, porque el método Swift espera unRange<String.Index>
, y no sabes cómo hacer uno de esos.La salida fácil es evitar que Swift se eclipse de esta manera, emitiendo explícitamente:
Tenga en cuenta que aquí no hay trabajo adicional significativo. "Emitir" no significa "convertir"; la Cadena es efectivamente una NSString. Solo le estamos diciendo a Swift cómo mirar esta variable para los propósitos de esta línea de código.
La parte realmente extraña de todo esto es que el método Swift, que causa todos estos problemas, no está documentado. No tengo idea de dónde se define; no está en el encabezado NSString y tampoco está en el encabezado Swift.
fuente
Range<String.Index>
u obtener este método indocumentado de nuestro camino.En el nuevo uso de Xcode 7.0
fuente
.advancedBy(0)
no es necesario para startIndex.La respuesta corta es que esto es realmente difícil en Swift en este momento. Mi presentimiento es que todavía hay mucho trabajo por hacer para Apple en métodos convenientes para cosas como esta.
String.substringWithRange()
está esperando unRange<String.Index>
parámetro, y por lo que puedo decir, no hay un método generador para elString.Index
tipo. Usted puede obtenerString.Index
los valores de vuelta deaString.startIndex
yaString.endIndex
y la llamada.succ()
o.pred()
sobre ellos, pero eso es una locura.¿Qué tal una extensión en la clase String que toma buenos
Int
s viejos ?Actualización: Swift beta 4 resuelve los siguientes problemas.
Tal como está [en beta 3 y anteriores], incluso las cadenas nativas de Swift tienen algunos problemas con el manejo de caracteres Unicode. El icono de perro anterior funcionó, pero lo siguiente no:
Salida:
fuente
NSString
me hizo pensar que estaba usando soloString
métodos nativos de Swift , ya que no estaba usando ningunamyString as NSString
llamada.Puedes usar estas extensiones para mejorar
substringWithRange
Swift 2.3
Swift 3
Uso:
fuente
Código de muestra para obtener subcadenas en Swift 2.0
(i) Subcadena del índice inicial
Entrada:-
Salida:-
(ii) Subcadena de un índice particular
Entrada:-
Salida:-
¡Espero que te ayude!
fuente
Solución fácil con poco código.
Cree una extensión que incluya subcadenas básicas que tienen casi todos los demás idiomas:
Simplemente llame a esto con
fuente
Esto funciona en mi patio de recreo :)
fuente
advance
Actualizado para Xcode 7. Agrega la extensión de cadena:
Utilizar:
Implementación:
fuente
prueba esto en el patio de recreo
te dará "ello, p"
Sin embargo, cuando esto se vuelve realmente interesante es que si hace que el último índice sea más grande que la cadena en el patio de recreo, mostrará las cadenas que definió después de str: o
Range () parece ser una función genérica, por lo que necesita saber el tipo con el que está tratando.
También debe darle la cadena real que le interesa en los parques infantiles, ya que parece contener todas las picaduras en una secuencia una tras otra con su nombre de variable después.
Entonces
da "ello, playground str Im the next string str2 "
funciona incluso si str2 se define con let
:)
fuente
Rob Napier ya había dado una respuesta asombrosa usando el subíndice. Pero sentí un inconveniente en eso, ya que no hay verificación para condiciones fuera de límite. Esto puede tender a fallar. Así que modifiqué la extensión y aquí está
Salida a continuación
Así que sugiero que siempre verifique si se deja
fuente
En Swift3
Por ejemplo: una variable "Duke James Thomas", necesitamos obtener "James".
fuente
Tomando una página de Rob Napier, desarrollé estas extensiones de cadena comunes , dos de las cuales son:
Uso:
fuente
Range
lugar deRange<String.Index>
gracias a la inferencia de tipos.Así es como obtienes un rango de una cadena:
El punto clave es que está pasando un rango de valores de tipo String.Index (esto es lo que devuelve el avance) en lugar de enteros.
La razón por la que esto es necesario es que las cadenas en Swift no tienen acceso aleatorio (debido a la longitud variable de los caracteres Unicode básicamente). Tampoco puedes hacer
str[1]
. String.Index está diseñado para funcionar con su estructura interna.Sin embargo, puede crear una extensión con un subíndice, que lo hace por usted, por lo que puede pasar un rango de enteros (ver, por ejemplo, la respuesta de Rob Napier ).
fuente
Traté de llegar a algo Pythonic.
Todos los subíndices aquí son geniales, pero las veces que realmente necesito algo simple es cuando quiero contar desde atrás, p. Ej.
string.endIndex.advancedBy(-1)
Admite
nil
valores, tanto para el índice inicial como para el final, dondenil
significaría un índice en 0 para el inicio,string.characters.count
para el final.EDITAR
Una solución más elegante:
fuente
Primero cree el rango, luego la subcadena. Puede usar la
fromIndex..<toIndex
sintaxis de esta manera:fuente
Aquí hay un ejemplo para obtener solo la identificación de video .ie (6oL687G0Iso) de toda la URL en forma rápida
fuente
Muestra completa que puedes ver aquí
fuente
http://www.learnswiftonline.com/reference-guides/string-reference-guide-for-swift/ muestra que esto funciona bien:
fuente
Bueno, tuve el mismo problema y lo resolví con la función "bridgeToObjectiveC ()":
Tenga en cuenta que en el ejemplo, substringWithRange junto con NSMakeRange toman la parte de la cadena que comienza en el índice 6 (carácter "W") y termina en el índice 6 + 6 posiciones adelante (carácter "!")
Salud.
fuente
Puede usar cualquiera de los métodos de subcadena en una extensión Swift String que escribí https://bit.ly/JString .
fuente
Si tiene un
NSRange
puente,NSString
funciona a la perfección. Por ejemplo, estaba haciendo algo de trabajoUITextFieldDelegate
y rápidamente quise calcular el nuevo valor de la cadena cuando me preguntó si debería reemplazar el rango.fuente
Extensión simple para
String
:fuente
Si no le importa el rendimiento ... esta es probablemente la solución más concisa en Swift 4
Te permite hacer algo como esto:
fuente