Recipe #2.1: String Comparison

    The Linden Scripting Language makes it very easy to compare two strings. To compare two strings, named stra and strb, use the following code:

if( stra == strb )
{
  llSay(0,”Equal.”);
}

    While this method of string comparison is good for determining whether two strings are exactly equal to each other, sometimes more advanced string comparison is called for. A script might need to determine whether two strings are equal, and ignore the case. Additionally, it might be necessary to determine which string would appear first in a dictionary.

    Recipe 2.1 meets these needs. This recipe can be seen in Listing 2.1.

Listing 2.1: String Comparison (StringCompare.lsl)

// From the book:
//
// Scripting Recipes for Second Life
// by Jeff Heaton (Encog Dod in SL)
// ISBN: 160439000X
// Copyright 2007 by Heaton Research, Inc.
//
// This script may be freely copied and modified so long as this header
// remains unmodified.
//
// For more information about this book visit the following web site:
//
// http://www.heatonresearch.com/articles/series/22/

string CHARS = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~";


integer compareLen(string a, string b,integer len)
{
    integer result = 0;
    if(a != b)
    {
        integer index = 0;
        do
        {
            string chara = llGetSubString(a,index,index);
            string charb = llGetSubString(b,index,index);
             
            integer posa = llSubStringIndex(CHARS ,chara);
            integer posb = llSubStringIndex(CHARS ,charb);
             
            if((posa >= 0) && (posb >= 0))
            {
                result = posa - posb;
            }
            else if(posa >= 0)
            {
                result = 1;
            }
            else if(posb >= 0)
            {
                result = -1;
            }
             
            if(result != 0) index = len;
            ++index;
                 
        }
        while(index < len);
    }
         
    return result;
}

integer compareNoCaseLen(string a, string b,integer len)
{
    string stra = llToLower(a);
    string strb = llToLower(b);
    return compareLen(stra,strb,len);
}

integer compare(string a, string b)
{
    integer lena = llStringLength(a);
    integer lenb = llStringLength(b);
    integer result;
    if(lena < lenb)
        result =  compareLen(a,b,lena);
    else
        result =  compareLen(a,b,lenb);
     
    return result;
}


integer compareNoCase(string a, string b)
{
    integer la = llStringLength(a);
    integer lb = llStringLength(b);
    string stra = llToLower(a);
    string strb = llToLower(b);
    integer result;
    if(la < lb)
        result =  compareNoCaseLen(stra,strb,la);
    else
        result =  compareNoCaseLen(stra,strb,lb);
     
    return result;
}

// Some test uses
default
{
    state_entry()
    {
        llSay(0, "compareNoCase(hello,HELLO): " + (string)compareNoCase("jeff","Jeff") );   
        llSay(0, "compare(hello,HELLO): " + (string)compare("jeff","Jeff") );   
        llSay(0, "compare(aaa,bbb): " + (string)compare("aaa","bbb") );   
        llSay(0, "compare(aaa,bbb): " + (string)compare("bbb","aaa") ); 
    }
} 

    This recipe begins by defining a variable, CHARS, which holds all of the characters that can be compared. This variable also defines the order in which characters will be sorted. This variable is declared as follows:

string CHARS = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~";

    For example, if the character “!” were to be compared to “#”, the string comparison function would report that “!” occurs first, and “#” second. This is because of the order of these two characters in the above list.

Using the compareLen Function

    To compare two strings, the compareLen function is provided.

integer compareLen(string a, string b,integer len)
{

    The compareLen function accepts three parameters. The first two are the strings to compare. The third parameter is the length of characters to compare. For example, if five were specified as the len variable, then characters zero through four would be compared.

    The compareLen function returns one of these three values.

  • Less than zero, string a is less than string b
  • Zero, string a and string b are equal
  • Greater than zero, string a is greater than string b

    A variable, named result is created to hold the result of the comparison. If the two strings are not equal, the program begins the process of determining which string occurs first alphabetically.

    integer result = 0;
    if(a != b)
    {
        integer index = 0;
        do
        {

    To determine which string occurs first alphabetically, a do/loop is used to loop across all of the characters in the string.

            string chara = llGetSubString(a,index,index);
            string charb = llGetSubString(b,index,index);

    The individual characters for each position are extracted from the strings.

            integer posa = llSubStringIndex(CHARS ,chara);
            integer posb = llSubStringIndex(CHARS ,charb);

     The position of each character is calculated. This numeric value allows the program to determine the alphabetical order of the two characters.

    If both posa and posb are greater than zero, both characters were found in the CHARS variable. If this is the case, the result will be the difference between them. If they are equal, this will result in a value of zero. If they are not equal, the result will hold a value either greater or less than zero, depending on whether posa or posb was greater.

            if((posa >= 0) && (posb >= 0))
            {
                result = posa - posb;
            }

    If character a was found, but not character b then return a value of one, which indicates that string a is greater than string b.

            else if(posa >= 0)
            {
                result = 1;
            }

    If character b was found, but not character a then return a value of negative one, which indicates that string b is greater than string a.

            else if(posb >= 0)
            {
                result = -1;
            }

    If the two characters were equal, continue with the loop.

            if(result != 0) index = len;
            ++index;

    Continue looping until the end of the string is reached.

        }
        while(index < len);
    }   
    return result;
}

    Finally, return the result.

Understanding the compareNoCaseLen Function

    Sometimes it is useful to compare two strings and ignore case. The compareNoCaseLen function does this. The compareNoCaseLen function accepts three parameters. The first two are the strings to compare. The third parameter is the length of characters to compare.

integer compareNoCaseLen(string a, string b,integer len)
{

    First, the two strings are converted to lower case.

    string stra = llToLower(a);
    string strb = llToLower(b);
    return compareLen(stra,strb,len);
}

    Finally, they are compared using the compareLen function discussed in the previous section.

Understanding the compare Function

    The two string functions presented so far allow a length to be specified. This can be very useful if only the first part of the strings should be compared. However, usually the entire string should be compared. The compare function compares the entire string.

integer compare(string a, string b)
{

    First, the length of each string is calculated.

    integer lena = llStringLength(a);
    integer lenb = llStringLength(b);

    The compareLen method is called to perform the comparison. The length of the smallest string is used in the comparison.

    integer result;
    if(lena < lenb)
        result =  compareLen(a,b,lena);
    else
        result =  compareLen(a,b,lenb);
     
    return result;
}

    Finally, the result is returned.

Understanding the compareNoCase Function

    The compareNoCase function works just like compareNoCaseLen, except that no length is provided. The entire string will be compared.

integer compareNoCase(string a, string b)
{

    First the length of each string is calculated.

    integer la = llStringLength(a);
    integer lb = llStringLength(b);

    Next, the strings are converted into lowercase.

    string stra = llToLower(a);
    string strb = llToLower(b);
    integer result;

    The compareLen method is called to perform the actual comparison. The length of the smallest string is used in the comparison.

    if(la < lb)
        result =  compareLen(stra,strb,la);
    else
        result =  compareLen(stra,strb,lb);
     
    return result;
}

    Finally, the result is returned.

Comparing Strings

    The script includes a simple state_entry function that tests the functions presented in this recipe.

default
{
    state_entry()
    {
        llSay(0, "compareNoCase(hello,HELLO): " + (string)compareNoCase("jeff","Jeff") );   
        llSay(0, "compare(hello,HELLO): " + (string)compare("jeff","Jeff") );   
        llSay(0, "compare(aaa,bbb): " + (string)compare("aaa","bbb") );   
        llSay(0, "compare(aaa,bbb): " + (string)compare("bbb","aaa") ); 
    }
}

    The output from this script is shown here.

[20:52]  Object: compareNoCase(hello,HELLO): 0
[20:52]  Object: compare(hello,HELLO): 31
[20:52]  Object: compare(aaa,bbb): -1
[20:52]  Object: compare(aaa,bbb): 1

    The above output demonstrates how the functions can be used.


Copyright 2005 - 2010 by Heaton Research, Inc.. Heaton Research™ and Encog™ are trademarks of Heaton Research. Click here for copyright and trademark information.