2009-05-06 28 views
67

Tengo una cadena en Lua y quiero iterar caracteres individuales en ella. Pero ningún código he intentado obras y el manual oficial sólo muestra cómo buscar y reemplazar subcadenas :(cómo iterar caracteres individuales en Lua string?

str = "abcd" 
for char in str do -- error 
    print(char) 
end 

for i = 1, str:len() do 
    print(str[ i ]) -- nil 
end 

Respuesta

101

en Lua 5.1, se puede recorrer de los caracteres de una cadena esto en un par de maneras

El bucle básico sería:.

 
for i = 1, #str do 
    local c = str:sub(i,i) 
    -- do something with c 
end 

Pero puede ser más eficaz utilizar un patrón con string.gmatch() para obtener un iterador sobre los personajes:

 
for c in str:gmatch"." do 
    -- do something with c 
end 

O incluso utilizar string.gsub() llamar a una función para cada carácter:

 
str:gsub(".", function(c) 
    -- do something with c 
end) 

En todo de los anteriores, he aprovechado el hecho de que el módulo string se establece como un metatabla para todos los valores de cadena, por lo que sus funciones se pueden llamar como miembros usando la notación :. También he usado el (nuevo en 5.1, IIRC) # para obtener la longitud de la cadena.

La mejor respuesta para su aplicación depende de muchos factores, y los puntos de referencia son su amigo si el rendimiento va a importar.

Es posible que desee evaluar qué que necesita para iterar sobre los personajes, y mirar a uno de los módulos de expresiones regulares que han sido unidos a Lua, o una visión moderna de mirar en el módulo de Roberto lpeg que implementa análisis sintáctico Grammers de expresión para Lua.

+0

Gracias. Acerca del módulo lpeg que ha mencionado: ¿guarda las posiciones de los tokens en el texto original después de la tokenización? La tarea que necesito realizar es sintaxis resaltar lenguaje simple específico en scite via lua (sin compilador de C++ compilado). Además, ¿cómo instalar lpeg? Parece que tiene una fuente .c en distribución, ¿necesita compilarse junto con lua? – grigoryvp

+0

La construcción de lpeg producirá una DLL (o .so) que debe almacenarse donde se requiera para encontrarla. (es decir, en algún lugar identificado por el contenido del paquete global.cpath en su instalación de lua). También debe instalar su módulo complementario re.lua si desea utilizar su sintaxis simplificada. A partir de una gramática de lpeg, puede obtener devoluciones de llamada y capturar texto de varias maneras, y ciertamente es posible usar capturas para simplemente almacenar la ubicación de la coincidencia para su uso posterior. Si el objetivo es resaltar la sintaxis, entonces un PEG no es una mala elección de herramienta. – RBerteig

+2

Sin mencionar las [últimas versiones de SciTE] (http: //www.scintilla.org/SciTEDownload.html) (desde 2.22) incluye Scintillua, un lexer basado en LPEG, lo que significa que puede funcionar desde el primer momento, sin necesidad de volver a compilar. –

10

Si utiliza Lua 5, Proveedores:

for i = 1, string.len(str) do 
    print(string.sub(str, i, i)) 
end 
4

Dependiendo de la tarea en cuestión, podría ser más fácil usar string.byte. También es la forma más rápida, ya que evita la creación de una nueva subcadena que resulta bastante costosa en Lua gracias a la creación de hash de cada nueva cadena y comprobar si ya se conoce. Puede precalcular el código de símbolos que busca con el mismo string.byte para mantener la legibilidad y la portabilidad.

local str = "ab/cd/ef" 
local target = string.byte("/") 
for idx = 1, #str do 
    if str:byte(idx) == target then 
     print("Target found at:", idx) 
    end 
end 
-1

Todas las personas sugieren un método menos óptimo

será lo mejor:

function chars(str) 
     strc = {} 
     for i = 1, #str do 
      table.insert(strc, string.sub(str, i, i)) 
     end 
     return strc 
    end 

    str = "Hello world!" 
    char = chars(str) 
    print("Char 2: "..char[2]) -- prints the char 'e' 
    print("-------------------\n") 
    for i = 1, #str do -- testing printing all the chars 
     if (char[i] == " ") then 
      print("Char "..i..": [[space]]") 
     else 
      print("Char "..i..": "..char[i]) 
     end 
    end 
+0

"Menos óptimo" para qué tarea? "Lo mejor" para qué tarea? –

Cuestiones relacionadas