Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Case insensitive array in Lua

Tags:

arrays

case

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
like image 770
lambgrp425 Avatar asked Sep 06 '11 00:09

lambgrp425


2 Answers

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
like image 104
daurnimator Avatar answered Oct 11 '22 18:10

daurnimator


  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
like image 40
Oleg V. Volkov Avatar answered Oct 11 '22 18:10

Oleg V. Volkov