05-30-09, 06:29 PM | #1 |
Large Scale Pattern Matching
I have a chat filter addon, and I'm looking to block out about 30 specific, yet slightly variable, messages. The variable parts of them are most likely to be player or pet names.
I'm a relative programming noob, so my initial instinct is just a giant block of "if strfind(text, pattern1) return true" type stuff. But that strikes me as both inefficient and messy to maintain/add to. So I come to you good people seeking a better way to accomplish this task. I had this initial thought to make things at least easier to maintain, if not more efficient: Code:
local filterPatterns = {"%a+ throws the ball to.*", "%a+ catches the ball!", etc. etc. };for i=1, #filterPatterns doif strfind(text, filterPatterns[i]) then return true; endend The other option I thought of was, since my variable factors are most likely to be units, to check each word using string.gmatch against UnitExists, then substitute that word with a pattern, which would allow me to use a table with my patterns as keys, I think. Code:
local filterPatterns = {["%a+ throws the ball to.*"] = true, ["%a+ catches the ball!"] = true, etc. etc. };local tmpText = text; --Unsure if it's okay to change text while iterating over it or not for word in string.gmatch(text, "%a+") doif UnitExists(word) thenend text = tmpText; return filterPatterns[text];tmpText = string.gsub(tmpText, word, "%a+");end Or am I just overcomplicating the whole matter and there won't be any problems with doing dozens of strfinds on each chat message that comes in? Thanks for any and all advice/comments. |
|
05-30-09, 07:49 PM | #2 |
I'm not sure why you need to compare anything against UnitExists. What is your overall goal with the pattern matching?
Otherwise, the most efficient way to do what you posted is to use an ipairs() loop: Code:
local filterPatterns = { "^%a+ throws the ball to.*", "^%a+ catches the ball!", } for i, pattern in ipairs(filterPatterns) do if text:match(pattern) then -- do stuff end end |
|
05-30-09, 10:58 PM | #3 | |
Edit - More clarification since I think I did a poor job at explaining what I wanted to do: "Joebob throws the ball to Mary" would get converted into "%a+ throws the ball to %a+", and instead of looping through my table comparing each table value to my text via text:match, then if it matches returning true, I could just use the raw pattern I had converted it to as a key, and that keyed tabled entry would be my true value, letting me just do a return filterPatterns[text];. (And it occurs to me now my original example filters would have to be changed for this to work) Thanks for the help! Last edited by Nirrudn : 05-30-09 at 11:10 PM. |
||
05-31-09, 12:29 PM | #4 | |
Code:
local filterPatterns = { "^%a+ throws the ball to ", "^%a+ catches the ball!", } local function filter(frame, event, message, sender, ...) for i, pattern in ipairs(filterPatterns) do if text:match(pattern) then -- do stuff end end end ChatFrame_AddMessageFilter("CHAT_MSG_TEXT_EMOTE", filter) ChatFrame_AddMessageFilter("CHAT_MSG_YELL", filter) -- repeat with all the chat message types you want to watch Code:
local filterPatterns = { "^%a+ throws the ball to ", "^%a+ catches the ball!", } local filterMessages = setmetatable({}, { __index = function(t, message) for i, pattern in ipairs(filterPatterns) do if message:match(pattern) then t[message] = true return true end end t[message] = false return false end }) local function filter(frame, event, message, sender, ...) if filterMessages[message] then -- do stuff end end ChatFrame_AddMessageFilter("CHAT_MSG_TEXT_EMOTE", filter) ChatFrame_AddMessageFilter("CHAT_MSG_YELL", filter) -- repeat with all the chat message types you want to watch |
||
05-31-09, 06:26 PM | #5 | |
Thanks for taking all the time to help me, it's been much appreciated and very informative for me. |
||
WoWInterface » Developer Discussions » Lua/XML Help » Large Scale Pattern Matching |
«
Previous Thread
|
Next Thread
»
|
Display Modes |
Linear Mode |
Switch to Hybrid Mode |
Switch to Threaded Mode |
|
|