Author Topic: Find The Closet Matching String  (Read 1214 times)

How would I find the closest matching string? For example if I did find("jes") it would find jes00.

I've built a function yesterday for one of my scripts.

It should be useful.

Code: [Select]
//THIS FUNCTION IS COMPARISON OF STRINGS
function ComparisonString(%StringInput,%StringSearch)
   {
      %ReturnTruth = strstr(%StringInput,%StringSearch);
      if(%ReturnTruth >= 0)
      {
         return true;
      }
   }

It will return true if it finds a match. For example,

"Hello I am Jes00."

it will find "Jes" in the "Jes00" and then report it's location since strstr only outputs -1 when it cant find a match it would always be 0 or higher if it did find a match.

I only started learning Torque script at the weekend so I'm sure someone will come up with something more effecient.

Hope that helps.

I've built a function yesterday for one of my scripts.

It should be useful.

Code: [Select]
//THIS FUNCTION IS COMPARISON OF STRINGS
function ComparisonString(%StringInput,%StringSearch)
   {
      %ReturnTruth = strstr(%StringInput,%StringSearch);
      if(%ReturnTruth >= 0)
      {
         return true;
      }
   }

It will return true if it finds a match. For example,

"Hello I am Jes00."

it will find "Jes" in the "Jes00" and then report it's location since strstr only outputs -1 when it cant find a match it would always be 0 or higher if it did find a match.

I only started learning Torque script at the weekend so I'm sure someone will come up with something more effecient.

Hope that helps.
He asked for the closest match, not the first match. Also, why not just do "strStr(%haystack, %needle) >= 0" instead of using a helper function?

He asked for the closest match, not the first match. Also, why not just do "strStr(%haystack, %needle) >= 0" instead of using a helper function?
I was thinking of the string containing only one copy of what was needed to be found.

So if,

"jes" were to be compared against "jes00" and "jes0".

That would then require a comparison of "jes00" and "jes0". Perhaps some sort of lettercount against each other to see which one has the better matching number of letters.

"jes0" would be the closest match.

Is that correct or have I messed up?

My code must have gotten a bit messy yesterday. I've taken your advice and simplified it thanks.

I was thinking of the string containing only one copy of what was needed to be found.

So if,

"jes" were to be compared against "jes00" and "jes0".

That would then require a comparison of "jes00" and "jes0". Perhaps some sort of lettercount against each other to see which one has the better matching number of letters.

"jes0" would be the closest match.

Is that correct or have I messed up?
Yeah. I guess you would first check if any started with the needle, and if so, filter the haystack to those. Then you could probably just get the shortest one.

It seems as if the OP is asking for a simple name completer. For example, I would use it like find("trey"); instead of find("Treynolds416");
The title is a bit misleading, but you would use the above code.

If you actually wanted to do something that found the closest string, you would use a different method than posted above. I like to think of it as sort a spell-check idea. One (or more letters, depending on how well you want this to work), would be replaced and cycled through the alphabet until a real word is found.

For example, I could type getClosestStr("difine"); and get "define" back. The script would run through lots of combinations:
Code: [Select]
"aifine"
"bifine"
"cifine"
"eifine"
"aifine"
...
...
...
"dcfine"
"ddfine"
"define" STOP

You could also make it 'smarter' in that it doesn't try consonants in certain points in the word, to save some computing power.

until a real word is found

This is the problem. You could have a gigantic list of words, but some things would still be missing and it would take a long time to initialize it anyway.

This is the problem. You could have a gigantic list of words, but some things would still be missing and it would take a long time to initialize it anyway.
Well, you could go the other way, starting with real words and replacing letters until they match the typed word. You could also do a rough sweep at first, to eliminate all of the choices that definitely are not the word, and redefine your sweep criteria over numerous passes.

Depending on how well you want it to work, it could be almost infinitely complex
« Last Edit: March 20, 2012, 03:38:06 PM by Treynolds416 »

It already has the list of names in a txt file. I want it to find (if there is one) the closest matching name that I tell it to.

Code: [Select]
function find(%str)
{
//File I/O stuff
%line = %file.readline();
if(strStr(%line,%str) != -1 && strLen(%str) <= strLen(%line))
return %line;
        else
                return 0;
//More File I/O stuff
}
This is very rudimentary code, but I'm pretty sure it will work for what you want to do

It assumes several things:
1) You have one name on each line in the text file, nothing more and nothing less
2) What you type into find(); will always have less or equal number of letters than the name on the line
3) What you type into find(); will always be part of a name, with no misspelled or misplaced characters

Code: [Select]
function find(%str)
{
//File I/O stuff
%line = %file.readline();
if(strStr(%line,%str) != -1 && strLen(%str) <= strLen(%line))
return %line;
        else
                return 0;
//More File I/O stuff
}
This is very rudimentary code, but I'm pretty sure it will work for what you want to do

It assumes several things:
1) You have one name on each line in the text file, nothing more and nothing less
2) What you type into find(); will always have less or equal number of letters than the name on the line
3) What you type into find(); will always be part of a name, with no misspelled or misplaced characters
Hmm, this is not working.
Code: [Select]
function getID(%name)
{
%file = new FileObject();
%file.openForRead("config/Client/ChatBot/BL_IDs.txt");

while(!%file.isEOF())
{
%badName = %file.readLine();
%ID = %file.readLine();
%blank = %file.readLine();

if(strStr(%badName, %name) != -1 && strLen(%name) <= strLen(%ID))
{
%file.close();
%file.delete();

return %ID;
}

%file.close();
%file.delete();

return %ID;
}

%file.close();
%file.delete();

return;
}

Why have you tried to close the file (2 times) in the while statement?

Why have you tried to close the file (2 times) in the while statement?
Because it returns and when it returns it ends the function.

Why have you tried to close the file (2 times) in the while statement?
My point is that you don't need several returns

Edit: I just took a better look at your code. Why also are you setting three variables to %file.readLine();?
« Last Edit: March 21, 2012, 02:35:34 PM by Treynolds416 »

stripos("Hello my name is jes00","jes");
This would return 17.