Case Insensitive Array in Lua

I am trying to program an addon for WoW (in lua). This is a word filter chat filter. I can't figure out how to make the array of these words be case insensitive, so any combination of upper / lower case words matches the array. Any ideas are 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 
+6
source share
3 answers
  • Define keywords outside the function. Otherwise, you recreate the table each time to delay this moment last, spending time for both creation and GC.
  • Convert your keywords to use this match in both upper and lower case letters.
  • You don't need capture data from a string, so use string.find for speed.
  • According to your logic, if you have several matches, you signal "false". since you only need 1 match, you do not need to count them. Just return false as soon as you click on it. Saves your time checking all other words too. If later you decide that you want more than one match, you better check it inside the cycle and come back as soon as you reach the desired score.
  • Do not use ipairs. This is slower than just for a loop from 1 to the length of the array, and ipairs is deprecated anyway in 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')) 

Result:

 true false false false true 
+3
source

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

==> this leads to a decrease in the number of arguments in string.find: therefore, case insensitive. I also used string.find because you probably need the "plain" option, which does not exist for string.match.

You can also easily return to 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 
+5
source

You can also organize this with metatables in a completely 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 

Thus, the table can be indexed in any case. If you add new words to it, it will also automatically reduce them. You can even customize it to fit with templates or whatever you want.

+1
source

Source: https://habr.com/ru/post/896674/


All Articles