<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://addonstudio.org/mw1/index.php?action=history&amp;feed=atom&amp;title=WoW%3AHOWTO%3A_Speed_up_string_match_lookups</id>
	<title>WoW:HOWTO: Speed up string match lookups - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://addonstudio.org/mw1/index.php?action=history&amp;feed=atom&amp;title=WoW%3AHOWTO%3A_Speed_up_string_match_lookups"/>
	<link rel="alternate" type="text/html" href="https://addonstudio.org/mw1/index.php?title=WoW:HOWTO:_Speed_up_string_match_lookups&amp;action=history"/>
	<updated>2026-06-02T02:20:27Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.39.3</generator>
	<entry>
		<id>https://addonstudio.org/mw1/index.php?title=WoW:HOWTO:_Speed_up_string_match_lookups&amp;diff=15282&amp;oldid=prev</id>
		<title>Move page script: Move page script moved page HOWTO: Speed up string match lookups to WoW:HOWTO: Speed up string match lookups without leaving a redirect</title>
		<link rel="alternate" type="text/html" href="https://addonstudio.org/mw1/index.php?title=WoW:HOWTO:_Speed_up_string_match_lookups&amp;diff=15282&amp;oldid=prev"/>
		<updated>2023-08-15T04:48:30Z</updated>

		<summary type="html">&lt;p&gt;Move page script moved page &lt;a href=&quot;/wiki/WoW:HOWTO:_Speed_up_string_match_lookups&quot; title=&quot;WoW:HOWTO: Speed up string match lookups&quot;&gt;HOWTO: Speed up string match lookups&lt;/a&gt; to &lt;a href=&quot;/wiki/WoW:HOWTO:_Speed_up_string_match_lookups&quot; title=&quot;WoW:HOWTO: Speed up string match lookups&quot;&gt;HOWTO: Speed up string match lookups&lt;/a&gt; without leaving a redirect&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 04:48, 15 August 2023&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-notice&quot; lang=&quot;en&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(No difference)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</summary>
		<author><name>Move page script</name></author>
	</entry>
	<entry>
		<id>https://addonstudio.org/mw1/index.php?title=WoW:HOWTO:_Speed_up_string_match_lookups&amp;diff=15281&amp;oldid=prev</id>
		<title>WoWWiki&gt;Starlightblunder: Label for Category:HOWTOs</title>
		<link rel="alternate" type="text/html" href="https://addonstudio.org/mw1/index.php?title=WoW:HOWTO:_Speed_up_string_match_lookups&amp;diff=15281&amp;oldid=prev"/>
		<updated>2007-06-01T14:30:19Z</updated>

		<summary type="html">&lt;p&gt;Label for Category:HOWTOs&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 14:30, 1 June 2007&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l169&quot;&gt;Line 169:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 169:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[Category:HOWTOs]]&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[Category:HOWTOs&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;|Speed up string match lookups&lt;/ins&gt;]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>WoWWiki&gt;Starlightblunder</name></author>
	</entry>
	<entry>
		<id>https://addonstudio.org/mw1/index.php?title=WoW:HOWTO:_Speed_up_string_match_lookups&amp;diff=15280&amp;oldid=prev</id>
		<title>WoWWiki&gt;Mikk at 09:39, 24 July 2006</title>
		<link rel="alternate" type="text/html" href="https://addonstudio.org/mw1/index.php?title=WoW:HOWTO:_Speed_up_string_match_lookups&amp;diff=15280&amp;oldid=prev"/>
		<updated>2006-07-24T09:39:32Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;When you have large number of patterns (dozens) to scan to find out which pattern is matching a given string, there&amp;#039;s a few things you can do to speed up the job.&lt;br /&gt;
&lt;br /&gt;
If the patterns are hard coded, there is of course any number of ways that you can be clever. But if you do not know what the patterns look like beforehand, which is the case when you&amp;#039;re trying to match input strings against patterns in [{{wdnlink|FrameXML/GlobalStrings.lua}} GlobalStrings.lua] using a formatstring-to-regex utility like [http://www.wowinterface.com/downloads/fileinfo.php?id=4809 BabbleLib&amp;#039;s] Deformat() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The approach below works by making lists of words used by patterns, and then looking at words in the input strings to determine which list(s) to look for matches in.&lt;br /&gt;
&lt;br /&gt;
Actually, the process is 2-pass. The first pass figures out the LEAST commonly used words, and then just uses those.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Note: The example contains a &amp;#039;&amp;#039;very&amp;#039;&amp;#039; simplistic &amp;quot;MyDeformatterFunc()&amp;quot; for converting &amp;quot;%s&amp;quot; to &amp;quot;(.*)&amp;quot;. It will not work for other locales than english. Do not use it in the real world, please.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;max-width: 80em; margin-right: 2em; height: 30em; overflow: scroll;&amp;quot;&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 -- Functions that we want called for different string matches&lt;br /&gt;
 function RoughPokeFunc(v1,v2) print(&amp;quot;RoughPokeFunc &amp;quot;..v1..&amp;quot; &amp;quot;..v2); end&lt;br /&gt;
 function SoftPokeFunc(v1,v2) print(&amp;quot;SoftPokeFunc &amp;quot;..v1..&amp;quot; &amp;quot;..v2); end&lt;br /&gt;
 function SoftNudgeFunc(v1,v2) print(&amp;quot;SoftNudgeFunc &amp;quot;..v1..&amp;quot; &amp;quot;..v2); end&lt;br /&gt;
 function ChickenFunc(v1,v2) print(&amp;quot;ChickenFunc &amp;quot;..v1..&amp;quot; &amp;quot;..v2); end&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 -- Strings to match mapped to functions that we want called&lt;br /&gt;
 MatchStrings = {&lt;br /&gt;
   [&amp;quot;%s roughly pokes %s&amp;quot;] = RoughPokeFunc,&lt;br /&gt;
   [&amp;quot;%s softly pokes %s&amp;quot;] = SoftPokeFunc,&lt;br /&gt;
   [&amp;quot;%s softly nudges %s&amp;quot;] = SoftNudgeFunc,&lt;br /&gt;
   [&amp;quot;%s gets nudged by %s and runs away screaming&amp;quot;] = ChickenFunc,&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 -- VERY simplistic deformatter function. &lt;br /&gt;
 -- You probably want a real deformatting library for this.&lt;br /&gt;
 function MyDeformatterFunc(str)	&lt;br /&gt;
   return (string.gsub(str, &amp;quot;%%s&amp;quot;, &amp;quot;(.*)&amp;quot;));&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 -- First run: count how many occurences there are of each word&lt;br /&gt;
 WordCounts = {}&lt;br /&gt;
 for str,func in MatchStrings do&lt;br /&gt;
   for word in string.gfind(str, &amp;quot;[^ ]+&amp;quot;) do&lt;br /&gt;
   	if(string.find(word, &amp;quot;^%%&amp;quot;)) then&lt;br /&gt;
   		-- ignore format strings&lt;br /&gt;
   	else&lt;br /&gt;
   		WordCounts[word] = (WordCounts[word] or 0) + 1;&lt;br /&gt;
   	end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 -- Second run: for each string, pick the least common word and place string in that hash bucket&lt;br /&gt;
 MatchStringsHash = {}&lt;br /&gt;
 for str,func in MatchStrings do&lt;br /&gt;
   local bestword, num;&lt;br /&gt;
   for word in string.gfind(str, &amp;quot;[^ ]+&amp;quot;) do&lt;br /&gt;
   	if(string.find(word, &amp;quot;^%%&amp;quot;)) then&lt;br /&gt;
   		-- ignore format strings&lt;br /&gt;
   	else&lt;br /&gt;
   		if(not num or WordCounts[word] &amp;amp;lt; num) then&lt;br /&gt;
   			num = WordCounts[word];&lt;br /&gt;
   			bestword = word;&lt;br /&gt;
   		end&lt;br /&gt;
   	end&lt;br /&gt;
   end&lt;br /&gt;
   &lt;br /&gt;
   assert(bestword);&lt;br /&gt;
   &lt;br /&gt;
   if(not MatchStringsHash[bestword]) then MatchStringsHash[bestword] = {}; end&lt;br /&gt;
   MatchStringsHash[bestword][MyDeformatterFunc(str)] = func;&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 WordCounts = nil; -- now we don&amp;#039;t need the counts anymore&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 -- Dump our MatchStringsHash on-screen so we can see what it looks like!&lt;br /&gt;
 print &amp;quot;Examining hash buckets&amp;quot;&lt;br /&gt;
 print &amp;quot;----------------------&amp;quot;&lt;br /&gt;
 for word,strings in MatchStringsHash do&lt;br /&gt;
   print(&amp;quot;  &amp;quot;..word..&amp;quot;:&amp;quot;);&lt;br /&gt;
   for str,func in strings do&lt;br /&gt;
   	print(&amp;quot;    \&amp;quot;&amp;quot;..str..&amp;quot;\&amp;quot;&amp;quot;);&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 -- Function that scans for matches and calls the resulting function&lt;br /&gt;
 function ScanForMatch(str)&lt;br /&gt;
   local bDone = false;&lt;br /&gt;
   local nCompares = 0;&lt;br /&gt;
   &lt;br /&gt;
   for word in string.gfind(str, &amp;quot;[^ ]+&amp;quot;) do&lt;br /&gt;
   	if(MatchStringsHash[word]) then&lt;br /&gt;
   		for pattern,func in MatchStringsHash[word] do&lt;br /&gt;
   			nCompares = nCompares + 1;&lt;br /&gt;
   			local success,_,v1,v2,v3,v4 = string.find(str, pattern);&lt;br /&gt;
   			if(success) then&lt;br /&gt;
   				func(v1,v2,v3,v4);&lt;br /&gt;
   				bDone=true;&lt;br /&gt;
   				break;&lt;br /&gt;
   			end&lt;br /&gt;
   		end&lt;br /&gt;
   	end&lt;br /&gt;
   	&lt;br /&gt;
   	if(bDone) then break; end&lt;br /&gt;
   end&lt;br /&gt;
 &lt;br /&gt;
   print(&amp;quot;  \&amp;quot;&amp;quot;..str..&amp;quot;\&amp;quot;: &amp;quot;..nCompares..&amp;quot; string.finds actually executed\n&amp;quot;);&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;&amp;quot;);&lt;br /&gt;
 print(&amp;quot;Executing!&amp;quot;);&lt;br /&gt;
 print(&amp;quot;----------&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 ScanForMatch(&amp;quot;Alice roughly pokes Bob&amp;quot;);&lt;br /&gt;
 ScanForMatch(&amp;quot;Bob softly pokes Charles&amp;quot;);&lt;br /&gt;
 ScanForMatch(&amp;quot;Charles softly nudges Denise&amp;quot;);&lt;br /&gt;
 ScanForMatch(&amp;quot;Denise gets nudged by Eve and runs away screaming&amp;quot;);&lt;br /&gt;
 ScanForMatch(&amp;quot;This string does not exist&amp;quot;);&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Running the above produces the following output:&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-right: 2em;&amp;quot;&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 Examining hash buckets&lt;br /&gt;
 ----------------------&lt;br /&gt;
   roughly:&lt;br /&gt;
     &amp;quot;(.*) roughly pokes (.*)&amp;quot;&lt;br /&gt;
   nudges:&lt;br /&gt;
     &amp;quot;(.*) softly nudges (.*)&amp;quot;&lt;br /&gt;
   gets:&lt;br /&gt;
     &amp;quot;(.*) gets nudged by (.*) and runs away screaming&amp;quot;&lt;br /&gt;
   softly:&lt;br /&gt;
     &amp;quot;(.*) softly pokes (.*)&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 Executing!&lt;br /&gt;
 ----------&lt;br /&gt;
 RoughPokeFunc Alice Bob&lt;br /&gt;
   &amp;quot;Alice roughly pokes Bob&amp;quot;: 1 string.finds actually executed&lt;br /&gt;
 &lt;br /&gt;
 SoftPokeFunc Bob Charles&lt;br /&gt;
   &amp;quot;Bob softly pokes Charles&amp;quot;: 1 string.finds actually executed&lt;br /&gt;
 &lt;br /&gt;
 SoftNudgeFunc Charles Denise&lt;br /&gt;
   &amp;quot;Charles softly nudges Denise&amp;quot;: 2 string.finds actually executed&lt;br /&gt;
 &lt;br /&gt;
 ChickenFunc Denise Eve&lt;br /&gt;
   &amp;quot;Denise gets nudged by Eve and runs away screaming&amp;quot;: 1 string.finds actually executed&lt;br /&gt;
 &lt;br /&gt;
   &amp;quot;This string does not exist&amp;quot;: 0 string.finds actually executed&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Problems with this approach ==&lt;br /&gt;
&lt;br /&gt;
There is no guarantee as to which order the string matches will be attempted.&lt;br /&gt;
&lt;br /&gt;
For example, assume these two patterns:&lt;br /&gt;
#&amp;quot;%s hits %s.&amp;quot;&lt;br /&gt;
#&amp;quot;%s hits %s hard.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Now, given the input string &amp;quot;Alice hits Bob.&amp;quot;, only #1 will match, and all is good.&lt;br /&gt;
&lt;br /&gt;
But with the input string &amp;quot;Alice hits Bob hard.&amp;quot;, there is NO guarantee which string will match. You can get #1 with the arguments &amp;quot;Alice&amp;quot;, &amp;quot;Bob hard&amp;quot;. Or you can get #2 with the arguments &amp;quot;Alice&amp;quot;, &amp;quot;Bob&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:HOWTOs]]&lt;/div&gt;</summary>
		<author><name>WoWWiki&gt;Mikk</name></author>
	</entry>
</feed>