Difference between revisions of "Associative Array Emulator"

From Second Life Wiki
Jump to navigation Jump to search
Line 3: Line 3:


Using this library is relatively simple.  To create a dictionary, declare it using:
Using this library is relatively simple.  To create a dictionary, declare it using:
<code>list dict=dictNew(<elements>);</code>
<br><code>list dict=dictNew(<elements>);</code>
 


<lsl>
<lsl>

Revision as of 21:04, 26 October 2008

This is a library to emulate associative arrays using lists. I've been using this code in more than a few projects and decided to release it here. From here on out I will call them 'dictionaries' or 'dicts' because I come from a FORTH background ^o.o^

Using this library is relatively simple. To create a dictionary, declare it using:
list dict=dictNew(<elements>);


<lsl> // Alynna's Dictionary Tools, released GPLv3, anyone can use it. Created by Alynna Vixen. Try // This library emulates dictionaries (associative arrays) using lists.

// Create a new dictionary, which just creates a list initialized with the number of data elements per key. // The initialized dictionary is returned, with no keys. list dictNew(integer elements) {

   return [elements];

}

// Delete an item from the dictionary. // If the key is not found or null, the result is an unchanged dictionary, // Else it is the dictionary with the key and its data removed. list dictDelItem(list dict, string dkey) {

   if (dkey == "") return dict; dkey = llToLower(dkey);
   list tmp = llList2List(dict,1,-1);
   integer elements = llList2Integer(dict,0);
   integer loc = llListFindList(llList2ListStrided(tmp,0,-1,elements+1),[dkey]);
   if (loc<0)
       return dict;
   else
       return [elements] + llDeleteSubList(tmp,loc*(elements+1),(loc*(elements+1))+elements);

}

// Set an item in the dictionary. // If the key is null, the dictionary is returned unchanged. // If the key is not found, it and the data is appended to the current dictionary, // Else, the data given replaces the data in the given key, the key remains unchanged. // The changed dictionary is returned. list dictSetItem(list dict, string dkey, list data) {

   if (dkey == "") return dict; dkey = llToLower(dkey);
   list tmp = llList2List(dict,1,-1);
   integer elements = llList2Integer(dict,0);
   integer loc = llListFindList(llList2ListStrided(tmp,0,-1,elements+1),[dkey]);
   if (loc<0)
       return dict + [dkey] + llList2List(data+[NULL_KEY,NULL_KEY,NULL_KEY,NULL_KEY,NULL_KEY,NULL_KEY,NULL_KEY,NULL_KEY],0,elements-1);
   else
       return [elements] + llListReplaceList(tmp, [dkey] + llList2List(data+[NULL_KEY,NULL_KEY,NULL_KEY,NULL_KEY,NULL_KEY,NULL_KEY,NULL_KEY,NULL_KEY],0,elements-1),loc*(elements+1),(loc*(elements+1)+elements));

}

// Get an item from the dictionary. // If the key is not found, or null, the result is an empty list. // If the key is found, the result is the list of values for that key in the dictionary. list dictGetItem(list dict, string dkey) {

   if (dkey == "") return []; dkey = llToLower(dkey);
   list tmp = llList2List(dict,1,-1);
   integer elements = llList2Integer(dict,0);
   integer loc = llListFindList(llList2ListStrided(tmp,0,-1,elements+1),[dkey]);
   if (loc<0)
       return [];
   else
       return llList2List(tmp,loc*(elements+1)+1,loc*(elements+1)+elements);

}

// Get a list of elements from the dictionary // If the element is -1, returns a list of all valid keys. // Else a list of the element values for every key is returned. list dictGetElems(list dict, integer elem) {

   list tmp = llList2List(dict,elem+2,-1);
   integer elements = llList2Integer(dict,0);
   return llList2ListStrided(tmp,0,-1,elements+1);

} // An alias for dictGetElems(<list>, -1) list dictGetKeys(list dict) {

   return dictGetElems(dict, -1);

}

// Set an element within an item in the dictionary. // The dictionary is returned unchanged, if the key is not found, the element out of range, or key is null. // Else, the dict is returned with the element changed. list dictSetElement(list dict, string dkey, integer elem, list data) {

   if (dkey == "") return dict; dkey = llToLower(dkey);
   list tmp = llList2List(dict,1,-1);
   integer elements = llList2Integer(dict,0);
   integer loc = llListFindList(llList2ListStrided(tmp,0,-1,elements+1),[dkey]);
   if (elem<0 || elem>elements-1) return dict;
   if (loc<0)
       return dict;
   else
       return [elements] + llListReplaceList(tmp, llList2List(data,0,0),loc*(elements+1)+(elem+1),(loc*(elements+1)+(elem+1)));

}

// Get a list of elements from the dictionary // If the element is -1, returns a list of all valid keys. // Else a list of the element values for every key is returned. list dictGetElement(list dict, string dkey, integer elem) {

   if (dkey == "") return []; dkey = llToLower(dkey);
   list tmp = llList2List(dict,1,-1);
   integer elements = llList2Integer(dict,0);
   integer loc = llListFindList(llList2ListStrided(tmp,0,-1,elements+1),[dkey]);
   if (loc>=0)
       return llList2List(tmp,loc*(elements+1)+(elem+1),loc*(elements+1)+(elem+1));
   else
       return [];

}

// Returns the position in the dictionary of a key. If it is not found, will return -1. // Good for testing for a key's existence. integer dictFindKey(list dict, string dkey) {

   if (dkey == "") 
       return -1;
   else {
       list tmp = llList2List(dict,1,-1);
       integer elements = llList2Integer(dict,0);
       return llListFindList(llList2ListStrided(tmp,0,-1,elements+1),[dkey]);
   }

}

// Simply returns the number of items in the dictionary. integer dictCount(list dict) {

   return (llGetListLength(dict)-1)/(llList2Integer(dict,0)+1);

}

// Delete the stuff below here its just for testing, unless you want to see how everything works. // In that case, drop this entire script into a box, compile it and click the box.

string stackdump(list x) {

   return "["+llDumpList2String(x, "] | [")+"]";

} default {

   touch_start(integer total_number)
   {
        llSay(0,"Begin AlyDictLib: One element tests.");
       llSay(0,"x = dictNew(1)");
       list x = dictNew(1);
       list y;
       llSay(0,"x: "+stackdump(x));
       llSay(0,"x = dictSetItem(x, 'kitty', ['cute'])");
       x = dictSetItem(x, "kitty", ["cute"]);
       llSay(0,"x: "+stackdump(x));
       llSay(0,"x = dictSetItem(x, 'puppy', ['cuter'])");
       x = dictSetItem(x, "puppy", ["cuter"]);
       llSay(0,"x: "+stackdump(x));
       llSay(0,"x = dictSetItem(x, 'foxy', ['cutest'])");
       x = dictSetItem(x, "foxy", ["cutest"]);
       llSay(0,"x: "+stackdump(x));
       llSay(0,"x = dictDelItem(x, 'kitty')");
       x = dictDelItem(x, "kitty");
       llSay(0,"x: "+stackdump(x));
       llSay(0,"x = dictSetItem(x, 'bunny', ['cute'])");
       x = dictSetItem(x, "bunny", ["cute"]);
       llSay(0,"x: "+stackdump(x));
       llSay(0,"x = dictSetItem(x, 'foxy', ['supercute'])");
       x = dictSetItem(x, "foxy", ["supercute"]);
       llSay(0,"x: "+stackdump(x));
       llSay(0,"y = dictGetItem(x, 'foxy')");
       y = dictGetItem(x, "foxy");
       llSay(0,"y: "+stackdump(y));
       llSay(0,"y = dictGetItem(x, 'bunny')");
       y = dictGetItem(x, "bunny");
       llSay(0,"y: "+stackdump(y));
       llSay(0,"y = dictGetElems(x, 0)");
       y = dictGetElems(x, 0);
       llSay(0,"y: "+stackdump(y));


       llSay(0,"y = dictGetKeys(x)");
       y = dictGetKeys(x);
       llSay(0,"y: "+stackdump(y));
       llSay(0," ---------- ");
       llSay(0,"Begin AlyDictLib: Multi element tests.");
       llSay(0,"x = dictNew(3)");
       x = dictNew(3);
       llSay(0,"x: "+stackdump(x));
       llSay(0,"x = dictSetItem(x, 'kitty', ['feline', 'cute', 'meow'])");
       x = dictSetItem(x, "kitty", ["feline", "cute", "meow"]);
       llSay(0,"x: "+stackdump(x));
       llSay(0,"x = dictSetItem(x, 'puppy', ['canine', 'cuter', 'bark'])");
       x = dictSetItem(x, "puppy", ["canine", "cuter", "bark"]);
       llSay(0,"x: "+stackdump(x));
       llSay(0,"x = dictSetItem(x, 'foxy', ['vulpine', 'cutest', 'yip'])");
       x = dictSetItem(x, "foxy", ["vulpine", "cutest", "yip"]);
       llSay(0,"x: "+stackdump(x));
       llSay(0,"x = dictDelItem(x, 'kitty')");
       x = dictDelItem(x, "kitty");
       llSay(0,"x: "+stackdump(x));
       llSay(0,"x = dictSetItem(x, 'bunny', ['lapine', 'cute', 'churr'])");
       x = dictSetItem(x, "bunny", ["lapine", "cute", "churr"]);
       llSay(0,"x: "+stackdump(x));
       llSay(0,"x = dictSetItem(x, 'foxy', ['vulpine', 'supercute', 'yerf'])");
       x = dictSetItem(x, "foxy", ["vulpine", "supercute", "yerf"]);
       llSay(0,"x: "+stackdump(x));
       llSay(0,"y = dictGetItem(x, 'foxy')");
       y = dictGetItem(x, "foxy");
       llSay(0,"y: "+stackdump(y));
       llSay(0,"y = dictGetItem(x, 'bunny')");
       y = dictGetItem(x, "bunny");
       llSay(0,"y: "+stackdump(y));
       llSay(0,"y = dictGetElems(x, 0)");
       y = dictGetElems(x, 0);
       llSay(0,"y: "+stackdump(y));
       llSay(0,"y = dictGetElems(x, 1)");
       y = dictGetElems(x, 1);
       llSay(0,"y: "+stackdump(y));
       llSay(0,"y = dictGetElems(x, 2)");
       y = dictGetElems(x, 2);
       llSay(0,"y: "+stackdump(y));
       llSay(0,"y = dictGetKeys(x)");
       y = dictGetKeys(x);
       llSay(0,"y: "+stackdump(y));
       llSay(0,"x = dictSetElement(x, 'foxy', 2, ['yip'])");
       x = dictSetElement(x, "foxy", 2, ["yip"]);
       llSay(0,"x: "+stackdump(x));
       llSay(0,"y = dictGetElement(x, 'bunny', 1)");
       y = dictGetElement(x, "bunny", 1);
       llSay(0,"y: "+stackdump(y));
       
       llSay(0,"dictFindKey(x, 'foxy'): "+(string)dictFindKey(x,"foxy"));
       llSay(0,"dictFindKey(x, 'ferret'): "+(string)dictFindKey(x,"ferret"));
       llSay(0,"dictCount(x): "+(string)dictCount(x));
       llSay(0," ---------- ");
       llSay(0,"Begin AlyDictLib: Error handling tests.");
       llSay(0,"x = dictNew(3)");
       x = dictNew(3);
       llSay(0,"x: "+stackdump(x));
       llSay(0,"Extra items: x = dictSetItem(x, 'kitty', ['feline', 'cute', 'meow', 'garbage'])");
       x = dictSetItem(x, "kitty", ["feline", "cute", "meow", "garbage"]);
       llSay(0,"x: "+stackdump(x));
       llSay(0,"Insufficient items: x = dictSetItem(x, 'puppy', ['canine', 'cuter'])");
       x = dictSetItem(x, "puppy", ["canine", "cuter"]);
       llSay(0,"x: "+stackdump(x));
       llSay(0,"Mixed items (technically NOT an error): x = dictSetItem(x, 'foxy', ['vulpine', 9001, 'yip'])");
       x = dictSetItem(x, "foxy", ["vulpine", 9001, "yip"]);
       llSay(0,"x: "+stackdump(x));
       llSay(0,"Set of null key: x = dictSetItem(x, , ['vulpine', 9001, 'yip'])");
       x = dictSetItem(x, "", ["vulpine", 9001, "yip"]);
       llSay(0,"x: "+stackdump(x));
       llSay(0,"Get of null key: y = dictGetItem(x, )");
       y = dictGetItem(x, "");
       llSay(0,"y: "+stackdump(y));
       llSay(0,"Deletion of non-existent item: x = dictDelItem(x, 'ferret')");
       x = dictDelItem(x, "ferret");
       llSay(0,"x: "+stackdump(x));
       llSay(0,"Addition of item: x = dictSetItem(x, 'bunny', ['lapine', 'cute', 'churr'])");
       x = dictSetItem(x, "bunny", ["lapine", "cute", "churr"]);
       llSay(0,"x: "+stackdump(x));
       llSay(0,"Correction of item: x = dictSetElement(x, 'puppy', 2, ['bark'])");
       x = dictSetElement(x, "puppy", 2, ["bark"]);
       llSay(0,"x: "+stackdump(x));
       llSay(0,"Get of non-existent item: y = dictGetItem(x, 'ferret')");
       y = dictGetItem(x, "ferret");
       llSay(0,"y: "+stackdump(y));
       llSay(0,"Get of null key: y = dictGetItem(x, )");
       y = dictGetItem(x, "");
       llSay(0,"y: "+stackdump(y));
       llSay(0,"Set of nonexistent element: x = dictSetElement(x, 'foxy', 4, ['yerf'])");
       x = dictSetElement(x, "foxy", 4, ["yerf"]);
       llSay(0,"x: "+stackdump(x));
       llSay(0,"Get of nonexistent element: y = dictGetElement(x, 'bunny', 6)");
       y = dictGetElement(x, "bunny", 6);
       llSay(0,"y: "+stackdump(y));
       
       llSay(0,"Set of nonexistent key: x = dictSetElement(x, , 4, ['yerf'])");
       x = dictSetElement(x, "", 4, ["yip"]);
       llSay(0,"x: "+stackdump(x));
       llSay(0,"Get of nonexistent key: y = dictGetElement(x, , 6)");
       y = dictGetElement(x, "", 6);
       llSay(0,"y: "+stackdump(y));                                      
   }

} </lsl>