cadenas en Lua son inmutables. Eso significa que cualquier solución que reemplace texto en una cadena debe terminar construyendo una nueva cadena con el contenido deseado. Para el caso específico de reemplazar un solo personaje con otro contenido, deberá dividir la cadena original en una parte de prefijo y una parte de postfijo, y volver a concatenarlos alrededor del nuevo contenido.
Esta variación en su código:
function replace_char(pos, str, r)
return str:sub(1, pos-1) .. r .. str:sub(pos+1)
end
es la traducción más directa con sencillo Lua. Probablemente sea lo suficientemente rápido para la mayoría de los propósitos. He arreglado el error que el prefijo deben ser los primeros pos-1
caracteres, y se han aprovechado del hecho de que si el último argumento de string.sub
falta que se supone que es -1
que es equivalente a la final de la cadena.
Pero tenga en cuenta que se crea una serie de cadenas temporales que quedarse en la tienda de cuerda hasta que la recolección de basura se los come. Los temporales para el prefijo y el sufijo no se pueden evitar en ninguna solución. Pero esto también tiene que crear un temporal para que el primer operador ..
sea consumido por el segundo.
Es posible que uno de los dos enfoques alternativos podrían ser más rápido. El primero es el solution offered by Paŭlo Ebermann, pero con un pequeño truco:
function replace_char2(pos, str, r)
return ("%s%s%s"):format(str:sub(1,pos-1), r, str:sub(pos+1))
end
Este utiliza string.format
para hacer el montaje del resultado con la esperanza de que puede adivinar el tamaño del búfer final sin necesidad de objetos adicionales temporales.
Pero tenga en cuenta que string.format
es probable que tenga problemas con cualquier \0
caracteres en cualquier cadena que pase a través de su formato %s
. Específicamente, ya que se implementa en términos de función estándar de C sprintf()
, sería razonable esperar que para terminar la cadena sustituido en la primera aparición de \0
. (Observado por el usuario Delusional Logic en un comentario.)
Una tercera alternativa que viene a la mente es la siguiente:
function replace_char3(pos, str, r)
return table.concat{str:sub(1,pos-1), r, str:sub(pos+1)}
end
table.concat
concatena eficientemente una lista de cadenas en un resultado final. Tiene un segundo argumento opcional que es texto para insertar entre las cadenas, que por defecto es ""
que se adapta a nuestro propósito aquí.
Supongo que a menos que sus cadenas sean enormes y haga esta sustitución con frecuencia, no verá ninguna diferencia práctica de rendimiento entre estos métodos. Sin embargo, me ha sorprendido antes, así que perfile su aplicación para verificar que haya un cuello de botella y compare las posibles soluciones cuidadosamente.
Gracias por la explicación en profundidad – dotminic
Esto es viejo. Pero acabo de resolver un error menor en algún código que escribí. Resulta que el método '' replace_char2'' no inserta caracteres nulos ('' \ 0''). –
@DelusionalLogic Buen punto. 'string.format' se basa sólidamente en la función' sprintf() 'de C estándar, y es probable que tenga problemas con los bytes NUL incrustados. – RBerteig