2011-09-06 12 views
6

Próbuję zaprogramować dodatek do WoW (w lua). Jest to filtr czatowy oparty na konkretnych słowach. Nie mogę wymyślić, jak sprawić, aby tablica tych słów była niewrażliwa na wielkość liter, tak aby kombinacja górnego/dolnego słowa pasowała do tablicy. Wszelkie pomysły będą mile widziane. Dzięki!Tablica niewrażliwa na luki w Lua

local function wordFilter(self,event,msg) 
local keyWords = {"word","test","blah","here","code","woot"} 
local matchCount = 0; 
    for _, word in ipairs(keyWords) do 
      if (string.match(msg, word,)) then 
      matchCount = matchCount + 1; 
     end 
    end 
    if (matchCount > 1) then 
      return false; 
    else 
     return true; 
    end 
end 

Odpowiedz

3
  1. Definiuj kluczowe słowa spoza funkcji. W przeciwnym razie ponownie tworzysz tabelę , aby chwilowo ją zmarnować, marnując czas zarówno na tworzenie, jak i na GC.
  2. Konwertuj słowa kluczowe na tupot pasujące do wielkich i małych liter.
  3. Nie potrzebujesz przechwyconych danych ze stringów, więc użyj string.find, aby uzyskać prędkość.
  4. Zgodnie z twoją logiką , jeśli masz więcej niż jeden mecz, sygnalizujesz "fałsz". Od potrzebujesz tylko 1 meczu, nie musisz ich liczyć. Po prostu zwróć false, jak tylko ją klikniesz. Oszczędza czas na sprawdzanie wszystkich pozostałych słów. Jeśli później zdecydujesz, że chcesz więcej niż jeden mecz , lepiej sprawdź to w wewnętrznej pętli i wróć, gdy tylko osiągniesz pożądany wynik.
  5. Nie używaj kart. Jest wolniejszy niż prosty dla pętli od 1 do długości tablicy, a ipairs jest i tak przestarzały w Lua 5.2.

    local keyWords = {"word","test","blah","here","code","woot"} 
    local caselessKeyWordsPatterns = {} 
    
    local function letter_to_pattern(c) 
        return string.format("[%s%s]", string.lower(c), string.upper(c)) 
    end 
    
    for idx = 1, #keyWords do 
        caselessKeyWordsPatterns[idx] = string.gsub(keyWords[idx], "%a", letter_to_pattern) 
    end 
    
    local function wordFilter(self, event, msg) 
        for idx = 1, #caselessKeyWordsPatterns do 
         if (string.find(msg, caselessKeyWordsPatterns[idx])) then 
          return false 
         end 
        end 
        return true 
    end 
    
    local _ 
    print(wordFilter(_, _, 'omg wtf lol')) 
    print(wordFilter(_, _, 'word man')) 
    print(wordFilter(_, _, 'this is a tEsT')) 
    print(wordFilter(_, _, 'BlAh bLAH Blah')) 
    print(wordFilter(_, _, 'let me go')) 
    

Wynik jest:

true 
false 
false 
false 
true 
5

Zastosowanie if msg:lower():find (word:lower() , 1 , true) then

==> to obniżyć przypadki oba argumenty string.find: stąd case niewrażliwość. Również użyłem string.find, ponieważ prawdopodobnie chcesz opcję "plain", która nie istnieje dla string.match.

Ponadto można łatwo powrócić na pierwsze słowo znaleziono:

for _ , keyword in ipairs(keywords) do 
    if msg:lower():find(keyword:lower(), 1, true) then return true end 
end 
return false 
1

Można również zorganizować z metatables, w całkowicie przejrzysty sposób:

mt={__newindex=function(t,k,v) 
    if type(k)~='string' then 
     error'this table only takes string keys' 
    else 
     rawset(t,k:lower(),v) 
    end 
end, 
__index=function(t,k) 
    if type(k)~='string' then 
     error'this table only takes string keys' 
    else 
     return rawget(t,k:lower()) 
    end 
end} 

keywords=setmetatable({},mt) 
for idx,word in pairs{"word","test","blah","here","code","woot"} do 
    keywords[word]=idx; 
end 
for idx,word in ipairs{"Foo","HERE",'WooT'} do 
    local res=keywords[word] 
    if res then 
     print(("%s at index %d in given array matches index %d in keywords"):format(word,idx,keywords[word] or 0)) 
    else 
     print(word.." not found in keywords") 
    end 
end 

ten sposób tabela może być indeksowane w każdym przypadku. Jeśli dodasz do niego nowe słowa, to automatycznie będzie również pisał małymi literami. Możesz go nawet dopasować, aby pasował do wzorców lub cokolwiek chcesz.