Lua中不区分大小写的数组

7

我正在尝试编写一个WoW的插件(使用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个回答

7

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

==> 这可以将两个参数转为小写字母以便在 string.find 中进行大小写不敏感的匹配。我使用了 string.find,因为您可能需要“plain”选项,而这种选项在 string.match 中是不存在的。

此外,您还可以轻松地返回第一个找到的单词:

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

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

结果如下:

true
false
false
false
true

2
你也可以通过元表来安排这个,完全透明地进行操作:
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

这样可以使表格无论大小写都可以被索引。如果您向其添加新单词,它也会自动将它们转换为小写。您甚至可以调整它以允许与模式匹配或任何您想要的内容进行匹配。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接