Difference between revisions of "LlParseString2List"

From Second Life Wiki
Jump to navigation Jump to search
(bug in the duplicate cleanup resulting in improper sorting of collisions for specificaly crafted input.)
m (<lsl> tag to <source>)
 
(39 intermediate revisions by 8 users not shown)
Line 1: Line 1:
{{LSL_Function
{{LSL_Function
{{#vardefine:p_src_desc|source string}}
{{#vardefine:p_separators_desc|separators to be discarded}}
{{#vardefine:p_spacers_desc|spacers to be kept}}
{{#vardefine:p_ParseStringKeepNulls_desc|boolean}}
|func_id=214|func_sleep=0.0|func_energy=10.0
|func_id=214|func_sleep=0.0|func_energy=10.0
|func=llParseString2List|return_type=list
|func=llParseString2List|return_type=list
|p1_type=string|p1_name=src|p2_type=list|p2_name=separators|p3_type=list|p3_name=spacers
|p1_type=string|p1_name=src|p1_desc=source string
|func_footnote='''separators''' and '''spacers''' must be lists of strings, maximum of 8 each.
|p2_type=list|p2_name=separators|p2_desc=separators to be discarded
|p3_type=list|p3_name=spacers|p3_desc=spacers to be kept
|func_footnote=In most situations [[llParseStringKeepNulls]] should be used instead. Discarding null values is rarely desired.
|func_desc
|func_desc
|return_text=that is '''src''' broken into a list, discarding '''separators''', keeping '''spacers''', discards any null values generated.
|return_text=that is {{LSLP|src}} broken into a list of strings, discarding {{LSLP|separators}}, keeping {{LSLP|spacers}}, discards any null (empty string) values generated.
|spec
|spec
|caveats=
|caveats=
*To avoid contradiction, every string of the '''{{LSL Param|spacers}}''' list of strings to keep must not exist in the '''{{LSL Param|separators}}''' list of strings to discard.
*All empty strings (that would arise from a spacer or separator being adjacent to each other or the ends) are removed;
*Every element in the list will be a string, no matter what you think it should be. Cast the results of [[llList2String]] to get what you want.
**If you want them (to keep the order of a list, for example) use [[llParseStringKeepNulls]] instead;
** ''integer my_int = (integer)llList2String(my_list, i);''
*Only the first 8 separators and first 8 spacers supplied will be used. Any beyond that will be ignored. To work around this see [[#Useful Snippets]] section below. The only limit on the number of items in the output is available script memory.
*[[llList2String]] is used here, as [[llList2Integer]] can only handle integers in simple notation, ie. will not handle hexadecimal integers.  
* All separators and spacers must be strings. All other types will be ignored;
|constants
* Separators take precedent over spacers. The string is parsed from start to finish. Each position is compared against the separators then spacers before moving onto the next position;
|examples=<pre>default
* Duplicate separators and spacers have no ill effects;
* All elements in the list returned by llParseString2List are strings, and must be explicitly typecast if they are to be used as other types. Do not rely upon the implicit typecasting of the other llList2* functions (as they typically return a default value);
* Remember to capture the result of the operation with a variable, unless you are planning to act directly on the results.
|examples=
<source lang="lsl2">default
{
{
     state_entry()
     state_entry()
Line 32: Line 34:
         llOwnerSay("<" + llDumpList2String(my_list,"><") + ">");
         llOwnerSay("<" + llDumpList2String(my_list,"><") + ">");
     }
     }
}</pre>
}</source>
|helpers=<div id="box">
== Function: [[list]] ParseString2List([[string]] {{LSL Param|src}}, [[list]] {{LSL Param|separators}}, [[list]] {{LSL Param|spacers}}, [[integer]] {{LSL Param|ParseStringKeepNulls}}); ==
<div style="padding: 0.5em;">
Returns a list that is '''{{LSL Param|src}}''' broken into a list, discarding '''{{LSL Param|separators}}''', keeping '''{{LSL Param|spacers}}'''.
<div style="padding: 0.0em 0.5em 0.5em 0.5em;" id="box">
===if '''{{LSL Param|ParseStringKeepNulls}}''' == [[FALSE]]===
Same as '''[[llParseString2List]]''', but not limited to 8 spacers or separators.


Thus substitute a call to the '''[[llParseString2List]]''' function by a call to '''ParseString2List''' whenever you have more than 8 separators or more than 8 spacers.
While LSL does not support lists-in-lists, you can emulate lists-in-lists by making successive calls or you could use {{LSLGC|JSON}}.
</div><div style="padding: 0.0em 0.5em 0.5em 0.5em;" id="box">
===if '''{{LSL Param|ParseStringKeepNulls}}''' != [[FALSE]]===
Same as '''[[llParseStringKeepNulls]]''', but not limited to 8 spacers or separators.


Thus substitute a call to the '''[[llParseStringKeepNulls]]''' function by a call to '''ParseString2List''' whenever you have more than 8 separators or more than 8 spacers.  
In this example some items have additional information supplied.
</div>
<source lang="lsl2">  
<pre>
string shoppinglist = "macaroni::pepperoni::bread#wheat::sausage#italian::coffee::syrup::apple::ice cream#strawberry#chocolate#vanilla";
list ParseString2List(string src, list separators, list spacers, integer ParseStringKeepNulls)
 
{//works just like llParseString2List and llParseStringKeepNulls but without
default
//the limits on spacers or separators
{
    list keys;
    state_entry()
    integer i = spacers != [];
    {
    integer offset;
        list items = llParseString2List(shoppinglist, ["::"], []);
    integer test;
        integer i = 0;
    list out;
        integer j = llGetListLength(items);
    string p;
         for(;i < j; ++i)
    while(i)
         if((p = llList2String(spacers, i = ~-i)))
         {
         {
             if(~(test = llSubStringIndex(src, p)))
             list desc = llParseString2List(llList2String(items, i), ["#"], []);
            if(llGetListLength(desc) > 1)
             {
             {
                 if(~(offset = llListFindList(out, (list)p)))
                 list types = llDeleteSubList(desc,0,0);
                 {
                 llOwnerSay("Item: "+ llList2String(desc, 0) + "  Type: " + llList2CSV(llDeleteSubList(types,-2,-1) + llDumpList2String(llList2List(types,-2,-1), " & ")));
                    out = llDeleteSubList(out, offset, offset);
            } else {
                    keys = llDeleteSubList(keys, -~(offset << 1), (-~offset) << 1);
                 llOwnerSay("Item: "+ (string)desc);
                }
                 keys = test + ((~i) + keys);
                out = p + out;
             }
             }
        }
    for(i = separators != [];i;)
        if((p = llList2String(separators, i = ~-i)))
        {
            if(~(test = llSubStringIndex(src, p)))
            {
                if(~(offset = llListFindList(out, (list)p)))
                {
                    out = llDeleteSubList(out, offset, offset);
                    keys = llDeleteSubList(keys, -~(offset << 1), (-~offset) << 1);
                }
                keys = test + (i + keys);
                out = p + out;
            }
        }
    out = [];
    offset = 0;
    while(keys)
    {
        list t = llList2List(llListSort(keys, 2, TRUE), 0, 1);
        integer r = llListFindList(keys, t);
        if((i = llList2Integer(t, 0)) < offset)
            keys = llDeleteSubList(keys, r, -~r);
        else
        {
            if(offset != i || ParseStringKeepNulls)
                out += llDeleteSubString(src, i - offset, -1);
            if(0x80000000 & test = llList2Integer(t, 1))
                out += p = llList2String(spacers, ~test);
            else
                p = llList2String(separators, test);
            src = llDeleteSubString(src, 0, ~(offset - (i += llStringLength(p))));
            offset = i;
            if(~(test = llSubStringIndex(src, p)))
                keys = llListReplaceList(keys, (list)(test + offset), r, r);
            else
                keys = llDeleteSubList(keys, r, -~r);
         }
         }
     }
     }
    if(src != "" || ParseStringKeepNulls)
}</source>
        return out + src;
|helpers=
    return out;
'''Examples of processing more than 8 spacers or separators:'''
}//Strife Onizuka
{{{!}}
</pre></div></div>
{{LSL DefineRow||[[ParseString2List]]|Functions exactly the same as [[llParseString2List]] and [[llParseStringKeepNulls]].}}
|also_functions=*{{LSLG|llParseStringKeepNulls}}
{{LSL DefineRow||[[Separate Words|separateWords]]|Functions exactly the same as [[llParseString2List]] unless you violate it's additional preconditions.
*{{LSLG|llDumpList2String}}
Appears to be correct at a glance.}}
*{{LSLG|llCSV2List}}
{{!}}}
*{{LSLG|llList2CSV}}
|also_functions={{LSL DefineRow||[[llParseStringKeepNulls]]}}
{{LSL DefineRow||[[llDumpList2String]]}}
{{LSL DefineRow||[[llCSV2List]]}}
{{LSL DefineRow||[[llList2CSV]]}}
|also_events
|also_events
|also_tests
|also_tests
|also_articles=*{{LSLG|Separate Words}}
|also_articles={{LSL DefineRow||[[Separate Words]]}}
*{{LSLG|LSLEditorBugs}}
{{LSL DefineRow||[[LSL-Editor/Bugs]]}}
|notes
|notes=If you indicate some items as separators, it will split the string where it finds the indicated separators, and strip out the separators.
 
If instead you indicate some items as spacers, it will split the string where it finds the spacers, but leave the spacers there, including them as separate entries in the result list.
 
<source lang="lsl2">string myString = "What Are You Looking At?";
 
llSay(0, llList2CSV( llParseString2List(myString,  ["W", "A", "Y", "L"], [] ) ) );
//returns:  hat , re , ou , ooking , t?
   
llSay(0, llList2CSV( llParseString2List(myString, [], ["W", "A", "Y", "L"] ) ) );
//returns: W, hat , A, re , Y, ou , L, ooking , A, t?</source>
 
Using " " as a separator will parse a sentence into words.
 
If there is no spacer you care about, just use <code>[]</code> as the spacer.
 
If an empty string is used as a separator or a spacer, it will have no effect.
|permission
|permission
|negative_index
|negative_index
Line 131: Line 101:
|cat3=Data Conversion
|cat3=Data Conversion
|cat4
|cat4
|history={{LSL Added|0.6.0|remote=http://secondlife.wikia.com/wiki/Version_0.6.0}}
}}
}}

Latest revision as of 13:08, 22 January 2015

Summary

Function: list llParseString2List( string src, list separators, list spacers );
0.0 Forced Delay
10.0 Energy

Returns a list that is src broken into a list of strings, discarding separators, keeping spacers, discards any null (empty string) values generated.

• string src source string
• list separators separators to be discarded
• list spacers spacers to be kept

In most situations llParseStringKeepNulls should be used instead. Discarding null values is rarely desired.

Caveats

  • All empty strings (that would arise from a spacer or separator being adjacent to each other or the ends) are removed;
  • Only the first 8 separators and first 8 spacers supplied will be used. Any beyond that will be ignored. To work around this see #Useful Snippets section below. The only limit on the number of items in the output is available script memory.
  • All separators and spacers must be strings. All other types will be ignored;
  • Separators take precedent over spacers. The string is parsed from start to finish. Each position is compared against the separators then spacers before moving onto the next position;
  • Duplicate separators and spacers have no ill effects;
  • All elements in the list returned by llParseString2List are strings, and must be explicitly typecast if they are to be used as other types. Do not rely upon the implicit typecasting of the other llList2* functions (as they typically return a default value);
  • Remember to capture the result of the operation with a variable, unless you are planning to act directly on the results.

Examples

default
{
    state_entry()
    {
        // This will say:
        // <A><crazy><fox><.><Saw><the><moon><.><.>
        string my_string = "A crazy fox.  Saw the moon..";
        list my_list = llParseString2List(my_string,[" "],["."]);
        llOwnerSay("<" + llDumpList2String(my_list,"><") + ">");
        
        // This will say:
        //  <A><crazy><fox><.><><><Saw><the><moon><.><><.><>
        my_list = llParseStringKeepNulls(my_string,[" "],["."]);
        llOwnerSay("<" + llDumpList2String(my_list,"><") + ">");
    }
}

While LSL does not support lists-in-lists, you can emulate lists-in-lists by making successive calls or you could use JSON.

In this example some items have additional information supplied.

   
string shoppinglist = "macaroni::pepperoni::bread#wheat::sausage#italian::coffee::syrup::apple::ice cream#strawberry#chocolate#vanilla";

default
{
    state_entry()
    {
        list items = llParseString2List(shoppinglist, ["::"], []);
        integer i = 0;
        integer j = llGetListLength(items);
        for(;i < j; ++i)
        {
            list desc = llParseString2List(llList2String(items, i), ["#"], []);
            if(llGetListLength(desc) > 1)
            {
                list types = llDeleteSubList(desc,0,0);
                llOwnerSay("Item: "+ llList2String(desc, 0) + "  Type: " + llList2CSV(llDeleteSubList(types,-2,-1) + llDumpList2String(llList2List(types,-2,-1), " & ")));
            } else {
                llOwnerSay("Item: "+ (string)desc);
            }
        }
    }
}

Useful Snippets

Examples of processing more than 8 spacers or separators:

•  ParseString2List Functions exactly the same as llParseString2List and llParseStringKeepNulls.
•  separateWords Functions exactly the same as llParseString2List unless you violate it's additional preconditions.

Appears to be correct at a glance.

Notes

If you indicate some items as separators, it will split the string where it finds the indicated separators, and strip out the separators.

If instead you indicate some items as spacers, it will split the string where it finds the spacers, but leave the spacers there, including them as separate entries in the result list.

string myString = "What Are You Looking At?";

llSay(0, llList2CSV( llParseString2List(myString,  ["W", "A", "Y", "L"], [] ) ) );
//returns:  hat , re , ou , ooking , t?
    
llSay(0, llList2CSV( llParseString2List(myString, [], ["W", "A", "Y", "L"] ) ) );
//returns: W, hat , A, re , Y, ou , L, ooking , A, t?

Using " " as a separator will parse a sentence into words.

If there is no spacer you care about, just use [] as the spacer.

If an empty string is used as a separator or a spacer, it will have no effect.

See Also

Functions

•  llParseStringKeepNulls
•  llDumpList2String
•  llCSV2List
•  llList2CSV

Articles

•  Separate Words
•  LSL-Editor/Bugs

Deep Notes

History

Footnotes

  1. ^ Early release notes were not very accurate or thorough, they sometimes included information about features added in previous releases or failed to include information about features added in that release.

Signature

function list llParseString2List( string src, list separators, list spacers );