Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

llSubStringIndex

Smithy Zeno
ownes 9 pet cacti
Join date: 3 Aug 2006
Posts: 52
02-10-2008 17:00
Hi everybody!
I figured I'd check out llSubStringIndex for a little script I'm working on, and I haven't had much luck. If anyone could check out the script below, which is supposed to search a list to see if the first letter of the message matches with any of the entries of the list, and fix it that'd be great.

-Smithy


CODE

list lower_letters = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"];

default
{
state_entry()
{
llListen(1,"",llGetOwner(),"");
}

listen(integer channel, string name, key id, string message)
{
llSetText(llGetSubString(message,0,0),<1,1,1>,1);
string thing = llGetSubString(message,0,0);
if(llSubStringIndex(lower_letters,thing) != -1)
{
llSay(0, "matches");
}
}
}

_____________________
-Smithy
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
02-10-2008 18:46
If you want to test if a letter is lower case I would do it this way:

CODE
if(llToUpper(letter) != letter)
{
//letter is lower case
}
_____________________
Truth is a river that is always splitting up into arms that reunite. Islanded between the arms, the inhabitants argue for a lifetime as to which is the main river.
- Cyril Connolly

Without the political will to find common ground, the continual friction of tactic and counter tactic, only creates suspicion and hatred and vengeance, and perpetuates the cycle of violence.
- James Nachtwey
Deanna Trollop
BZ Enterprises
Join date: 30 Jan 2006
Posts: 671
02-10-2008 20:07
From: Smithy Zeno

list lower_letters = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"];

[snip]

if(llSubStringIndex(lower_letters,thing) != -1)
The variable lower_letters is a list, but you're trying to pass it to llSubStringIndex, which expects a string. You want to either make lower_letters just a string consisting of the characters a-z, OR instead use:

if( llListFindList( lower_letters, (list)thing ) != -1 )

Personally, I'd use the string. It would use less memory, and I'd think it would search faster, though I'm not entirely sure on the latter.
Rob Adelaide
Cream Cheese Fanatic
Join date: 19 Oct 2006
Posts: 34
02-10-2008 20:27
llSubStringIndex is best for finding a word in a sentence, usually when listening to chat. You can use it like:

CODE

default
{
state_entry()
{
llListen(0, "", NULL_KEY, "");
}

listen(integer num, string nam, key id, string msg)
{
if (0 == llSubStringIndex(llKey2Name(llGetOwner)))
{
llSay(0, "Hey, that's my owner!");
}
}
}


This will listen to open chat and if it ever hears your name spoken it will say "Hey, that's my owner!" At least, this is how I understand it to work.

The reason I think you have to check to see if it equals 0 is because it will return an index(matrix/list) of whenever it finds the thing you're looking for in the sentence, and if it finds at least one that index will be 0 or greater. I know for a fact if it doesn't hear anything that it is looking for in this scenario, it returns -1 instead of 0, so it won't say anything.

-R

PS: If you read this Void Singer, the reason I pass NULL_KEY instead of "" is just my own peace of mind. It doesn't take up any more communication or space when being passed to another item because it is compiled when run, which compiles NULL_KEY to a 0-bit instead of the string or constant you type in LSL, whatever it may be.
Hewee Zetkin
Registered User
Join date: 20 Jul 2006
Posts: 2,702
02-10-2008 21:37
Hey Rob. Couple of small suggestions:

1. Unless you are or have very recently been in the same sim as the object with that script, it is likely to get an empty string for your name. You might want to grab the owner's name when the script first starts up (the owner is likely to be around then), or use llRequestAgentData(), which can retrieve a resident's name even if they are offline or not present. If you do it this way, you'll probably want to test for changes in ownership as well.

2. The llSubStringIndex() function searches for one string within another, so you'll have to use two arguments. Something like 'if (llSubStringIndex(message, ownerName) >= 0)' if you are looking for the owner's name anywhere in the message. It sounds like you may realize this bit already, but I want it to be clear for the other readers.
Rob Adelaide
Cream Cheese Fanatic
Join date: 19 Oct 2006
Posts: 34
02-10-2008 22:06
Hewee, thanks for the heads-up.

1. I have been using various scripts with llKey2Name for over a year, and never once realized that it only works properly if the object who's key it is converting is in the same sim(or in a sim that can see the sim as of 1.9 - gee, thanks LL). IMHO this is very VERY broken, as any object or agent with a key should be able to properly look up its name(or another script should be able to do so), regardless of whether what it's looking up is in the same sim or not. I had intended this script more as an example though, something to be used in an attachment probably, which is why it wouldn't matter either way. Dataserver is EVIL when it comes to causing lag and slowing down scripts, so I avoid it as much as possible in everything I do, unless a feature requires it somehow such as reading from a notecard.

2. You're right on this one, and I do realize it. If you have more than one instance of something that llSubStringIndex is checking for, it will return a value greater than 0. For example, if you were to say someone's name twice in a single chat message around this thing, it wouldn't work properly because the index would no longer be 0, it would then be 1. If you say the name 3 times in a single chat, the index would be 2, etc. I'm not sure on the accuracy of this information, this is just how I assume it works, and what my understanding of an index is.

-R
Osgeld Barmy
Registered User
Join date: 22 Mar 2005
Posts: 3,336
02-10-2008 23:40
heres the breakdown

your looking for "a"

you would use substring index if your index looks like this
string index = "abcdefghijklmnopqrstuvwxyz";

where as you have a list which would require llListFindList() to search

strings are smaller in memory, as far as search times they are about the same
Deanna Trollop
BZ Enterprises
Join date: 30 Jan 2006
Posts: 671
02-11-2008 00:11
From: Rob Adelaide
2. You're right on this one, and I do realize it. If you have more than one instance of something that llSubStringIndex is checking for, it will return a value greater than 0. For example, if you were to say someone's name twice in a single chat message around this thing, it wouldn't work properly because the index would no longer be 0, it would then be 1. If you say the name 3 times in a single chat, the index would be 2, etc. I'm not sure on the accuracy of this information, this is just how I assume it works, and what my understanding of an index is.
This is incorrect. llSubStringIndex returns the character offset (the index) of the first instance of the string being searched for inside the string being searched. For example:

llSubStringIndex( "This is a test", "is" )

will return 5, because the first character of "is" is the 6th character of the first string (the first character being 0). Searching for "s" will return 3, not because there are 3 "s"es in the string, but because the first "s" is the 4th character.

If the string being searched for is does not appear in the string being searched, -1 is returned.
Hewee Zetkin
Registered User
Join date: 20 Jul 2006
Posts: 2,702
02-11-2008 00:16
From: Rob Adelaide
If you have more than one instance of something that llSubStringIndex is checking for, it will return a value greater than 0. For example, if you were to say someone's name twice in a single chat message around this thing, it wouldn't work properly because the index would no longer be 0, it would then be 1. If you say the name 3 times in a single chat, the index would be 2, etc. I'm not sure on the accuracy of this information, this is just how I assume it works, and what my understanding of an index is.

Oh. Actually, what the index refers to is the POSITION (starting at zero) of the substring within the larger string. Here are some examples of the results of 'llSubStringIndex(str, "BLAH";)', with the result listed before the value of 'str':

0 "BLAH hahaha hello"
1 "0BLAHbakaslfkj"
2 "01BLAH basketball field"
3 "012BLAHBLAHBLAHBLAHBLAHBLAHBLAHBL...fooled you"
4 "abc BLAH whatchagonnadoaboutit?"
12 "blahblahblahBLAH - Yeah, it's case sensitive and all!"
-1 "thisstringdoesn'tcontainthatstringyouarelookingfor"

EDIT: Oops. Deanna beat me to it. That's what I get for letting myself be distracted in the middle of writing a reply. Heh heh. :)
Smithy Zeno
ownes 9 pet cacti
Join date: 3 Aug 2006
Posts: 52
02-11-2008 03:13
Thanks for so many replies everyone!
_____________________
-Smithy
Squirrel Wood
Nuteater. Beware!
Join date: 14 Jun 2006
Posts: 471
02-11-2008 06:34
// Convert first letter of a string to upper case...
string test = "abc123";
test = (test = "";) + llToUpper(llGetSubString(test,0,0)) + llGetSubString(test,1,-1);
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
02-11-2008 10:09
From: Squirrel Wood
// Convert first letter of a string to upper case...
string test = "abc123";
test = (test = "";) + llToUpper(llGetSubString(test,0,0)) + llGetSubString(test,1,-1);


That is going to yield the wrong result if the string only has one character in it. What you should do is this:
string test = "abc123";
test = (test = "";) + llToUpper(llGetSubString(test,0,0)) + llDeleteSubString(test,0,0);
_____________________
Truth is a river that is always splitting up into arms that reunite. Islanded between the arms, the inhabitants argue for a lifetime as to which is the main river.
- Cyril Connolly

Without the political will to find common ground, the continual friction of tactic and counter tactic, only creates suspicion and hatred and vengeance, and perpetuates the cycle of violence.
- James Nachtwey