开发者

Case insensitive array in Lua

I'm trying to program an addon for WoW (in lua). It's a chat filter based on specific words. I can't figure out how to get the array of these words to be case insensitive, so that any upper/lower case combination of the word matches the array. Any ideas would be greatly appreciated. Thanks!

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


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

==> it lower cases both of the arguments to string.find: hence case insensitivity. Also I used string.find because you probably want the 'plain' option, which doesn't exist for string.match.

Also you can easily return on the first word found:

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


  1. Define keyWords outside of function. Otherwise you're recreating table every time just to thorw it away moments latter, wasting time on both creation and GC.
  2. Convert keyWords to patter that match both upper and lower case letters.
  3. You don't need captured data from string, so use string.find for speed.
  4. According to your logic, if you've got more than one match you signal 'false'. Since you need only 1 match, you don't need to count them. Just return false as soon as you hit it. Saves you time for checking all remaining words too. If later you decide you want more than one match, you still better check it inside loop and return as soon as you've reached desired count.
  5. Don't use ipairs. It's slower than simple for loop from 1 to array length and ipairs is deprecated in Lua 5.2 anyway.

    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'))
    

Result is:

true
false
false
false
true


You can also arrange this with metatables, in an entirely transparent way:

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

This way the table can be indexed in whatever case. If you add new words to it, it will automatically lower-case them too. You can even adjust it to allow matching with patterns or whatever you'd like.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜