Le stringhe in Lua sono immutabili. Ciò significa che qualsiasi soluzione che sostituisce il testo in una stringa deve finire per costruire una nuova stringa con il contenuto desiderato. Per il caso specifico di sostituzione di un singolo carattere con altri contenuti, è necessario suddividere la stringa originale in una parte di prefisso e una parte di postfix e concatenarli di nuovo attorno al nuovo contenuto.
Questa variazione sul vostro codice:
function replace_char(pos, str, r)
return str:sub(1, pos-1) .. r .. str:sub(pos+1)
end
è la traduzione più diretta per semplici Lua. Probabilmente è abbastanza veloce per la maggior parte degli scopi. Ho risolto il bug che il prefisso dovrebbe essere il primo pos-1
caratteri e ha approfittato del fatto che se manca l'ultimo argomento a string.sub
si presume che sia -1
che equivale alla fine della stringa.
Ma si noti che crea un certo numero di stringhe temporanee che si bloccheranno nell'archivio di stringhe finché la raccolta di dati inutili non le mangerà. I provvisori per il prefisso e il suffisso non possono essere evitati in nessuna soluzione. Ma anche questo deve creare un temporaneo per il primo operatore ..
da consumare dal secondo.
È possibile che uno dei due approcci alternativi possa essere più veloce. Il primo è il solution offered by Paŭlo Ebermann, ma con un piccolo ritocco:
function replace_char2(pos, str, r)
return ("%s%s%s"):format(str:sub(1,pos-1), r, str:sub(pos+1))
end
Questo utilizza string.format
per fare il montaggio del risultato, nella speranza che si può indovinare la dimensione del buffer finale senza bisogno di oggetti aggiuntivi temporanei.
Ma attenzione che è possibile che string.format
abbia problemi con qualsiasi \0
caratteri in qualsiasi stringa che passa attraverso il suo formato %s
. In particolare, poiché è implementato in termini di funzione sprintf()
di C standard, è ragionevole aspettarsi che termini la stringa sostituita alla prima occorrenza di \0
. (Annotato dall'utente Delusional Logic in un commento.)
Una terza alternativa che viene in mente è questa:
function replace_char3(pos, str, r)
return table.concat{str:sub(1,pos-1), r, str:sub(pos+1)}
end
table.concat
concatena in modo efficiente una lista di stringhe in un risultato finale. Ha un secondo argomento opzionale che è il testo da inserire tra le stringhe, che per impostazione predefinita è ""
che si adatta al nostro scopo qui.
La mia ipotesi è che a meno che le stringhe non siano enormi e si effettui spesso questa sostituzione, non si noteranno differenze di prestazioni pratiche tra questi metodi. Tuttavia, sono stato sorpreso prima, quindi profila la tua applicazione per verificare che ci sia un collo di bottiglia e per valutare attentamente le possibili soluzioni.
Grazie per la spiegazione approfondita – dotminic
Questo è vecchio. Ma ho appena finito di risolvere un bug minore in qualche codice che ho scritto. Risulta che il metodo '' replace_char2'' non inserisce caratteri null ('' \ 0''). –
@DelusionalLogic Buon punto. 'string.format' si basa solidamente sulla funzione' sprintf() 'di C standard, ed è probabile che abbia problemi con i byte NUL incorporati. – RBerteig