8
votes

Modification d'un personnage dans une corde en Lua

Y a-t-il un moyen de remplacer un caractère à la position n dans une chaîne de la Lua.

C'est ce que j'ai monté jusqu'à présent: P>

function replace_char(pos, str, r)
    return str:sub(pos, pos - 1) .. r .. str:sub(pos + 1, str:len())
end

str = replace_char(2, "aaaaaa", "X")
print(str)


0 commentaires

3 Réponses :


5
votes

Vous devez utiliser POS à l'intérieur de votre fonction au lieu de littéral 1 et 3 , mais en dehors de cela, il semble bon. Comme les chaînes Lua sont immuables, vous ne pouvez pas vraiment faire beaucoup mieux que cela.

Peut-être xxx

est plus efficace que l'opérateur .. / code> , mais j'en doute - s'il s'avère être un goulot d'étranglement, mesurez-le (puis décidez d'implémenter cette fonction de remplacement en C).


10 commentaires

Oui, l'opérateur .. / code> est le moyen le plus lent de concaténer des chaînes car une nouvelle chaîne est créée pour chaque .. . Les méthodes plus rapides incluent string.format et table.concat . Cela ne devrait causer aucun effet notable, sauf si vous travaillez avec de très grandes chaînes ou de nombreuses opérations de concaténation. Par exemple, j'ai eu un script utilisant plus de 500 Mo de mémoire pour traiter un fichier de moins de 1 Mo en utilisant environ 5 .. par ligne d'entrée lors du tri et de la reconstruction de l'entrée comme sortie. Changer pour stocker des chaînes dans une table et table.concat à la fin le rendit si vite que je n'ai même pas pris la peine de mesurer.


@Arrowmaster: Savez-vous que dans a .. b .. c Il y en a deux (au lieu d'une seule) nouvelles chaînes créées ou présumez-vous simplement cela? En principe, cela pourrait être optimisé par le compilateur / interprète pour créer une seule nouvelle chaîne, comme s'il est fait en Java pour l'opérateur + . Votre exemple est un autre cas, car vous devez vraiment créer de nouvelles chaînes avec chaque relevé.


@ Paŭlo Ebermann Ouais Je viens de copier le code, j'ai oublié de supprimer les littéraux. @Arrowmaster @ Paŭlo Ebermann Je vais comparer le .. Opérateur à la méthode du format. Merci pour la perspicacité.


@ Paŭlo: La version de référence de Lua n'a pas grand-chose si des optimisations de compilateur. Je ne suis pas sûr d'autres implémentations telles que Luajit.


Vous avez besoin de parens autour de "% s% s% s" ici.


À propos des optimisations: Autant que je me souvienne, Standard Lua essaie de transformer toutes les concatenations .. dans une seule expression à une seule instruction VM (jusqu'à un point). Donc a .. b .. c ne crée pas de chaîne intermédiaire. (Mais a .. (b .. c) devrait en créer un.)


Et généralement table.concat (et la création de table qu'elle a besoin) ne valent que la peine dans les boucles. Si vous avez une seule expression, allez pour .. . (Et de toute façon, vous ne devriez pas essayer d'optimiser prématurément; écrivez-le de manière la plus concise d'abord, profilez et optimisez plus tard)


Lua a un opcode spécial "Concat" qui ne crée pas de chaînes intermédiaires. L'utilisation de parenthèses provoque la création de chaînes intermédiaires.


Fait ou pas? Le "soit" me jette.


@Rosscharette: Je suppose que c'est "ça ne" pas ". Mais vous devriez inclure un @sylvanaar dans votre message afin qu'il obtient une notification à ce sujet.



14
votes

Les cordes de Lua sont immuables. Cela signifie que toute solution qui remplace le texte dans une chaîne doit finir par construire une nouvelle chaîne avec le contenu souhaité. Pour le cas spécifique de remplacement d'un seul caractère avec une autre teneur, vous devrez diviser la chaîne d'origine en une partie de préfixe et une pièce postfix, et de les concaténer autour du nouveau contenu.

Cette variation de votre code: P>

function replace_char3(pos, str, r)
    return table.concat{str:sub(1,pos-1), r, str:sub(pos+1)}
end


3 commentaires

Merci pour l'explication en profondeur


C'est vieux. Mais je viens de faire résoudre un insecte mineur dans un code que j'ai écrit. Éteint que la méthode remplacer_char2 n'insérez pas NULL ( \ 0 ) caractères.


@DelusionAlogic bon point. String.Format est basé solidement sur la fonction SPRINTF (CODE> STRINTF () STRINTF () et est susceptible d'avoir des problèmes avec des octets nul intégrés.



-1
votes

avec Luajit, vous pouvez utiliser la bibliothèque FFI pour lancer la chaîne dans une liste de graphiques non signés: xxx


0 commentaires