Métodos de cadenas

Las cadenas incluyen propiedades y métodos para gestionar su contenido.

Propiedades#

PropiedadDescripción
lenLongitud total en caracteres
hashIdentificador numérico único
texto = "DinoCode"
print texto.len
print texto.hash

Características del hash#

¿Para qué sirve?

DinoCode optimiza varias operaciones con cadenas calculando un valor número único (hash) que representa a la cadena. De este modo, es más fácil y rápido para el intérprete identificar y encontrar una cadena en ciertos contextos.

¿Es costoso?

No exactamente. Cuando se crean nuevas cadenas el hash no se calcula en ese momento, es perezoso. Solo se calcula la primera vez que:

  • Se accede a él a través de la propiedad hash
  • Se interna la cadena usando el método .intern()
  • Se utiliza la cadena como una clave en un objeto

Una vez calculado, se almacena en caché por lo que acceder a él múltiples veces es muy eficiente.

# El hash perezoso ocurre en cadenas dinámicas
texto = "2 + 2 = ${2 + 2}"

print texto.hash  # Se calculo en este momento
print texto.hash  # Se leyó del caché
Hash aleatorio por sesión

Por seguridad el hash cambia en cada sesión. Es decir, si ejecutamos el mismo programa varias veces, el hash para la misma cadena será diferente en cada una de esas sesiones.

Métodos#

MétodoDescripción
intern()Interna la cadena en memoria para optimización
char_at(i)Devuelve el carácter en la posición i
concat(s)Concatena la cadena s al final
contains(s)true si contiene la subcadena s
starts_with(s)true si empieza con s
ends_with(s)true si termina con s
trim()Elimina espacios en blanco a los extremos
trim(chars)Elimina caracteres específicos a los extremos
to_uppercase()Convierte a mayúsculas
to_lowercase()Convierte a minúsculas
repeat(n)Repite la cadena n veces
split()Divide la cadena por los espacios, devolviendo un array
split(delim)Divide la cadena usando un delimitador
replace(a b)Reemplaza ocurrencias de a por b
substr(ini fin)Extrae texto desde el índice ini hasta fin
substr(ini)Extrae texto desde el índice ini hasta el final
index_of(s)Índice de la primera aparición de s
index_of(s pos)Busca s a partir del índice pos
last_index_of(s)Índice de la última aparición de s
last_index_of(s pos)Busca s hacia atrás desde pos
pad_left(w)Rellena a la izquierda con espacios hasta longitud w
pad_left(w c)Rellena a la izquierda usando el carácter c
pad_right(w)Rellena a la derecha con espacios hasta longitud w
pad_right(w c)Rellena a la derecha usando el carácter c

Características del interning - .intern()#

¿En qué consiste?

El interning consiste en evitar duplicaciones innecesarias de una cadena. Las cadenas internadas comparten una misma referencia en memoria si son completamente iguales.

¿Qué ventajas tiene?

DinoCode reconoce las cadenas que fueron internadas. Lo que le permite optimizar radicalmente las comparaciones entre ellas, ya que en lugar de comparar el contenido, solo compara sus referencias (mismo rendimiento que comparar dos números en Rust).

¿Qué desventajas tiene?

Para que el interning funcione debemos pagar un costo de cómputo en el momento en que internamos la cadena (.intern()) que consiste en calcular el hash de la cadena y buscarlo dentro de una tabla centralizada. Aunque encontrar el elemento en la tabla es casi instantáneo, el proceso completo tiene un costo real que crece según el tamaño de la cadena.

# El interning no es necesario en cadenas constantes
# el compilador ya se encargó de internarlas
texto1 = "Hola, me llamo Ismael"
texto2 = "Hola, me llamo Ismael"

# Ya comparten la misma referencia en memoria
print id(texto1) " es igual a " id(texto2)

# Cuando creamos una cadena dinámica
#  perdemos la ventaja del interning porque
#  no se pudo internar en tiempo de compilación
nombre = "Ismael"
texto3 = "Hola, me llamo $nombre"

print id(texto3) " es diferente de " id(texto1)

# Si usamos intern() el intérprete se encargara
# de internar la cadena
texto4 = "Hola, me llamo $nombre".intern()

print id(texto4) " es igual a " id(texto1)
Perezoso por naturaleza

El interning es perezoso por naturaleza. Básicamente pagas un pequeño precio al procesar la cadena al principio a cambio de obtener comparaciones instantáneas después.

Ejemplos#

Longitud y validación#

texto = "Hola Mundo"

print texto.len        # 10

if texto.starts_with("Hola")
    print "Empieza con Hola"
if texto.ends_with("Mundo")
    print "Termina con Mundo"
if texto.contains("Mundo")
    print "Contiene Mundo"

Transformaciones#

texto = "  Hola Mundo  "

print texto.trim()          # "Hola Mundo"
print texto.to_uppercase()  # "  HOLA MUNDO  "
print texto.to_lowercase()  # "  hola mundo  "
print "Hi".repeat(3)        # "HiHiHi"

Búsqueda y extracción#

texto = "Hola Mundo"

print texto.index_of("Mundo")  # 5
print texto.substr(0 4)        # "Hola"
print texto.substr(5)          # "Mundo"
print texto.replace("Mundo" "Dino") # "Hola Dino"

División y Padding#

# División
frutas = "manzana,uva".split(",")
print frutas    # ["manzana" "uva"]
print frutas[1] # "uva"

# Relleno (Padding)
numero = "42"
print numero.pad_left(5 "0")   # "00042"
print numero.pad_right(5 "-")  # "42---"