2009-05-06 4 views
67

Ich habe eine Zeichenfolge in Lua und möchte einzelne Zeichen darin iterieren. Aber kein Code, den ich habe Werke versucht, und das offizielle Handbuch zeigt nur, wie Substrings zu finden und ersetzen :(Wie man einzelne Zeichen in Lua String iteriert?

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

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

Antwort

101

In lua 5.1, Sie können die Zeichen einer Zeichenfolge dieses in ein paar Möglichkeiten iterieren

Die grundlegende Schleife würde.

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

Aber es kann effizienter sein, ein Muster mit string.gmatch() zu verwenden einen Iterator über die Charaktere zu bekommen:

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

Oder sogar string.gsub() zu verwenden, um eine Funktion für jedes Zeichen zu nennen:

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

In allen des oben genannten habe ich die Tatsache ausgenutzt, dass das Modul string als eine Metatabelle für alle Zeichenfolgenwerte festgelegt ist, so dass seine Funktionen als Elemente unter Verwendung der :-Notation aufgerufen werden können. Ich habe auch die (neu zu 5.1, IIRC) # verwendet, um die String-Länge zu erhalten.

Die beste Antwort für Ihre Anwendung hängt von vielen Faktoren ab, und Benchmarks sind Ihr Freund, wenn die Leistung eine Rolle spielt.

Sie möchten vielleicht bewerten, warum Sie müssen über die Charaktere zu durchlaufen, und in einem der regulären Ausdruck Module zu suchen, die zu Lua oder für einen modernen Ansatz gebunden wurden Blick in lpeg Modul Roberto die Parsing implementiert Ausdruck Grammers für Lua.

+0

Dank. Über das von Ihnen erwähnte lpeg-Modul: Speichert es Token-Positionen im Originaltext nach der Tokenisierung? Die Aufgabe, die ich ausführen muss, besteht darin, spezifische einfache Sprache in scite mittels lua hervorzuheben (ohne kompilierten C++ - Parser). Wie installiert man Lpeg? Scheint, dass es .c Quelle in der Distribution hat - muss es zusammen mit lua kompiliert werden? – grigoryvp

+0

Wenn Sie lpeg erstellen, wird eine DLL (oder .so) erstellt, die gespeichert werden soll, wo sie benötigt wird. (d. h. irgendwo durch den Inhalt des globalen Paketes.cpath in Ihrer lua-Installation identifiziert.) Sie müssen auch sein Begleitmodul re.lua installieren, wenn Sie seine vereinfachte Syntax verwenden wollen. Von einer lpeg-Grammatik aus können Sie Callbacks erhalten und Text auf verschiedene Arten erfassen, und es ist sicherlich möglich, Captures zu verwenden, um den Speicherort der Übereinstimmung für die spätere Verwendung zu speichern. Wenn Syntax-Highlight das Ziel ist, dann ist ein PEG keine schlechte Wahl des Tools. – RBerteig

+2

Ganz zu schweigen von den [neuesten Versionen von SciTE] (http://www.scintilla.com).org/SciTEDownload.html (seit 2.22) enthält Scintillua, einen LPEG-basierten Lexer, was bedeutet, dass es sofort einsatzbereit ist und keine erneute Kompilierung erforderlich ist. –

10

Wenn Sie mit Lua 5, versuchen:

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

Abhängig von der jeweiligen Aufgabe ist es möglicherweise einfacher, string.byte zu verwenden. Es ist auch der schnellste Weg, weil es vermeidet, neue Teilstrings zu erstellen, die in Lua ziemlich teuer sind, dank Hashing jeder neuen Zeichenkette und Überprüfung, ob es bereits bekannt ist. Sie können den Code der Symbole, die Sie suchen, mit demselben string.byte vorberechnen, um die Lesbarkeit und Portabilität zu erhalten.

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

Alle Menschen deuten auf eine weniger optimale Methode

Wird am besten:

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

"Weniger optimal" für welche Aufgabe? "Best" für welche Aufgabe? –