How to make a search bar?

Hello, I’m making a dictionary (name +icon) to be looped through and inserted into a gui. I have a search bar that will update every time the textbox detects input, my only issue is indexing my dictionary with the search parameters. I know I can use string.gmatch but that’s not what im looking for, I want the closest match to the search parameters, how would I do that?

Thanks

9 Likes

I made a search function based off a Levenshtein distance algorithm a few months ago for someone asking a similar question. I don’t remember how accurate the results were, but I think it might be suitable for your use case?

local function FuzzySearch(ComparisonStrings, SearchString)
	local SearchResults = {}
	
	for _,ComparisonString in pairs(ComparisonStrings) do
		local ComparisonStringLength = #ComparisonString
		local SearchStringLength = #SearchString
		
		if SearchStringLength <= ComparisonStringLength + 5 then
			
			local TempComparisonString = ComparisonString:lower()
			local TempSearchString = SearchString:lower()
			
			local Cost
			
			local Rows = ComparisonStringLength  + 1
			local Columns = SearchStringLength + 1
			
			local Distance = {}
		
			for i = 1, Rows do
				Distance[i] = {}
				
				for k = 1, Columns do
					Distance[i][k] = 0
				end
			end
			
			for i = 2, Rows do
				for k = 2, Columns do
					Distance[i][1] = i
					Distance[1][k] = k
				end
			end
			
			for i = 2, Columns do
				for k = 2, Rows do
					if TempComparisonString:sub(k - 1, k - 1) == TempSearchString:sub(i - 1, i - 1) then
						Cost = 0
					else
						Cost = 2
					end
					
					Distance[k][i] = math.min(
						Distance[k - 1][i] + 1,
						Distance[k][i - 1] + 1,
						Distance[k - 1][i - 1] + Cost
					)
				end
			end
			
			table.insert(SearchResults, 
				{
					Ratio = ((ComparisonStringLength + SearchStringLength) - Distance[Rows][Columns]) / (ComparisonStringLength + SearchStringLength),
					Word = ComparisonString
				}
			)
		else
			table.insert(SearchResults,
				{
					Ratio = 0,
					Word = ComparisonString
				}
			)
		end
	end
	
	table.sort(SearchResults, function(A, B)
		return A.Ratio > B.Ratio
	end)
	
	return SearchResults -- Returns in the format of { { Ratio, Word }, { Ratio, Word } }. A ratio of 1 means it completely matches and a ratio of 0 means nothing matches at all.
end

local TestStrings = {"Wooden Arrow", "Iron Arrow", "Steel Arrow", "Iron Sword", "Iron Boots", "Iron Pickaxe"}
local SearchString = "Arrow"

local Results = FuzzySearch(TestStrings, SearchString) -- Returns most relevant results first

for _,Result in pairs(Results) do -- Prints "Iron Arrow, Steel Arrow, Wooden Arrow, Iron Sword, Iron Boots, Iron Pickaxe"
	print(Result.Word, Result.Ratio)
end
39 Likes

Wow thanks! I’ll try it later and see if it works

1 Like

It works :slight_smile:
image

3 Likes