2011-09-06 4 views
6

와우 (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 

답변

3
  1. function 외부의 키워드를 정의하십시오. 그렇지 않다면 당신은 테이블을 만들 때마다 테이블을 다시 만들려고합니다. 생성 및 GC 모두에 시간을 낭비합니다.
  2. 대문자와 소문자 모두 일치하는 과 일치하는 키 워드를 패턴으로 변환하십시오.
  3. 문자열에서 캡처 한 데이터 이 필요하지 않으므로 속도를 위해 string.find를 사용하십시오.
  4. 논리에 따르면 일치 항목이 둘 이상인 경우 '거짓'신호를 보냅니다. 이후로 1 경기 만 필요하므로 계산할 필요가 없습니다. 치기하자마자 바로 을 거짓으로 반환하십시오. 나머지 단어도 모두 확인하는 시간을 절약 할 수 있습니다. 나중에 하나 이상의 이 필요하다고 결정하면 루프 내에서 확인하고 더 이상 에 도달하자마자 반환하십시오.
  5. ipairs를 사용하지 마십시오. 그것은 1에서 배열 길이까지 간단한 for 루프보다 느리고 ipua는 루아 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')) 
    

결과는 다음과 같습니다

true 
false 
false 
false 
true 
5

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

==>이 낮은 경우 인수 모두 string.find합니다 : 따라서 소문자 구분. 또한 string.match에 존재하지 않는 '보통'옵션을 원하기 때문에 string.find를 사용했습니다. 또한

쉽게 발견 된 첫 번째 단어를 반환 할 수 있습니다

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

또한 완전히 투명한 방법으로, 메타 테이블에이를 정렬 할 수 있습니다 : 테이블을 인덱싱 할 수

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 

이 방법 어쨌든. 새 단어를 추가하면 자동으로 소문자로 바뀝니다. 패턴이나 원하는대로 일치하도록 조정할 수도 있습니다.

관련 문제