Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

sort lists by variable

Blain Candour
Registered User
Join date: 17 Jun 2005
Posts: 83
08-12-2005 07:00
Does anyone know how to make the list sort function sort integers? I tried typecasting integers to strings and sorting, sorting directly as integers, padding the numbers to make it alphanumeric(a-z style) compatible, etc. It refuses to work.

Noone on live help when I was looking into this was big into lists. I wound up writing custom functions to go through the convoluted process of typecasting and padding padding numbers, converting them to letters, sorting the list, then converting back to numbers and typecasting to integer again when I use the list.

While this works and was nice practice for my LSL problem solving skills it is also quite silly. I have convinced myself that I am simply missing something and that the list sort function really isn't so stupid it can not tell wether 1 comes before 2. Someone help me out here.

I'd rather feel like I did lots of work over a simple mistake and then correct it so it can cut out the conversion overhead than think that LL would really make a sort function that can not even count.
Jef Ambassador
Empathetic Extropian
Join date: 1 May 2005
Posts: 9
08-12-2005 09:59
From: Blain Candour
Does anyone know how to make the list sort function sort integers? I tried typecasting integers to strings and sorting, sorting directly as integers, padding the numbers to make it alphanumeric(a-z style) compatible, etc. It refuses to work.


Sorting lists by an integer field works well for me, can you post some example code?

- Jef
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
08-12-2005 10:24
are you storing the result? it's a common mistake to call the function and then not store the result. Your not the first to think there was a bug with llListSort (and you probably won't be the last). Welcome to scripting in LSL.

CODE

list junk = [1,6,3,8,4,9,2,7,5,0];

//will run but will discard the result
llListSort(junk, 1, 1);
llOwnerSay((string)junk);

//stores the result.
junk = llListSort(junk, 1, 1);
llOwnerSay((string)junk);

_____________________
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
Zeno Concord
To infinity, and beyond!
Join date: 28 Mar 2005
Posts: 51
08-12-2005 17:18
In the wiki for llListSort there is a relevant comment:
From: someone

To sort a basic list with no strides, use a value of 0 for stride.
-- GunzourYellowknife (2004-06-26 22:42:27)
Blain Candour
Registered User
Join date: 17 Jun 2005
Posts: 83
08-14-2005 00:26
I was definately storing the list.

I went back and did some testing. I don't have my original code any more but I think my problem lies in how stringed numbers are sorted. I was sending data through linktell with comma seperated string and then parsing it, sorting it, then truncating the end if it overflows my set number of strides.

Instead of converting my strided integers from string to integer before sort and plugging them back into the list I was sorting then converting to integer. I could have sworn I tried converting to integer before sort and it failed but if I did I must have done it incorrectly since it works fine now.

I appreciate the responses.

Well.. the follwing are not very useful to me now but with a little alteration they would make a good place to start in converting start paramater integers into keys for on rez or something.

CODE

string digit2letter(string digit)
{
if (digit == "9")digit = "A";
else if (digit == "8")digit = "B";
else if (digit == "7")digit = "C";
else if (digit == "6")digit = "D";
else if (digit == "5")digit = "E";
else if (digit == "4")digit = "F";
else if (digit == "3")digit = "G";
else if (digit == "2")digit = "H";
else if (digit == "1")digit = "I";
else if (digit == "0")digit = "J";
return digit;
}

string letter2digit(string letter)
{
if (letter == "Z")letter = "0";
else if (letter == "A")letter = "9";
else if (letter == "B")letter = "8";
else if (letter == "C")letter = "7";
else if (letter == "D")letter = "6";
else if (letter == "E")letter = "5";
else if (letter == "F")letter = "4";
else if (letter == "G")letter = "3";
else if (letter == "H")letter = "2";
else if (letter == "I")letter = "1";
else if (letter == "J")letter = "0";
return letter;
}

string Integer2Alphabet(string score2)
{
string NewScore;
integer scorelength = llStringLength(score2);
integer ii;
for (ii=0;ii < scorelength;ii++)
{
string CurrentDigit = digit2letter(llGetSubString(score2,ii,ii));
NewScore = (NewScore + CurrentDigit);
}

integer i;
for (i=scorelength;i < maxDigits;i++)
{
NewScore = "Z" + NewScore;
}
return NewScore;
}


string Alphabet2Integer(string score2)
{
string NewScore;
integer scorelength = llStringLength(score2);
integer ii;
for (ii=0;ii < scorelength;ii++)
{
string CurrentDigit = letter2digit(llGetSubString(score2,ii,ii));
NewScore = (NewScore + CurrentDigit);
}

integer i;
for (i=scorelength;i < maxDigits;i++)
{
NewScore = "Z" + NewScore;
}
return NewScore;
}



converting back to integer removed the padding. heh. Atleast it was amusing to write.
a lost user
Join date: ?
Posts: ?
08-14-2005 00:55
Have a look at the llListSort() delcaration...

list llListSort(list src, integer stride, integer ascending)

it actually returns the result of the sort as a new list.. so..
llListSort(junk,1,1);

Doesn't actually do anything because there is nowhere for the result to be returned to.

Try this instead:
junk = llListSort(junk,1,1);

or simply:
llOwnerSay((string)(llListSort(junk,1,1));
Blain Candour
Registered User
Join date: 17 Jun 2005
Posts: 83
08-14-2005 03:23
Yeah. I was storing the list. I just wasn't using actual integers I think. Was using stringed integers.
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
08-15-2005 09:51
both digit2letter and letter2digit are simple hashes. For fun lets combine them into a single function ^^

CODE

string digit2letter(string digit)
{
if (digit == "9")digit = "A";
else if (digit == "8")digit = "B";
else if (digit == "7")digit = "C";
else if (digit == "6")digit = "D";
else if (digit == "5")digit = "E";
else if (digit == "4")digit = "F";
else if (digit == "3")digit = "G";
else if (digit == "2")digit = "H";
else if (digit == "1")digit = "I";
else if (digit == "0")digit = "J";
return digit;
}

string letter2digit(string letter)
{
if (letter == "Z")letter = "0";
else if (letter == "A")letter = "9";
else if (letter == "B")letter = "8";
else if (letter == "C")letter = "7";
else if (letter == "D")letter = "6";
else if (letter == "E")letter = "5";
else if (letter == "F")letter = "4";
else if (letter == "G")letter = "3";
else if (letter == "H")letter = "2";
else if (letter == "I")letter = "1";
else if (letter == "J")letter = "0";
return letter;
}


CODE

return letterdigithash(string input)
{
integer a = ~llSubStringIndex("ABCDEFGHIJ0123456789", input);
if(!a) return input;
return llGetSubString("ABCDEFGHIJ0123456789", a, a);
}
_____________________
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
Blain Candour
Registered User
Join date: 17 Jun 2005
Posts: 83
08-16-2005 03:42
I didn't realize the use of tilde as a bitwise complement operator was in LSL. :P
(I looked that up, don't I sound all smurt?)

That is a lot cleaner. It actually wouldn't work for what I was using it for without some editing though. I was padding the number with Z's and then converting both Z's and J to 0. Then converting back to integer would remove the padding automatically.

CODE

string letterdigithash(string input)
{
integer a = ~llSubStringIndex("ZABCDEFGHIJ01234567890", input);
if(!a) return input;
return llGetSubString("ZABCDEFGHIJ01234567890", a, a);
}


Works great though since the first index of 0 is J and the Z padding is added before running letterdigithash(). Thanks for the tip. ~ is my new friend.
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
08-16-2005 11:37
hehe it's all cool, just hardly ever get to use the bitwise not operator.

Since the two functions you listed are the same when using the hash function lets have some fun^^

++i is faster then i++ (LSL does not do any optimization)
when any variable is declaired it is set a value, if you don't set one it is given a default value. If speed is an issue then it is important not to waste these opertunities. Since we don't use "i" again after the first loop we can recycle it as the counter for the second. Since the second loop pickups where the first one ends we don't have to initialize the value.

CODE

string IntegerAlphabetHash(string score2)
{
string NewScore;
integer scorelength = llStringLength(score2);
integer i = 0;
while(i < scorelength)
{
NewScore += letterdigithash(llGetSubString(score2,i,i));
++i;
}
while(i < maxDigits)
{
NewScore = "Z" + NewScore;
++i;
}
return NewScore;
}


If we needed to use the hash table 3 or more times it would be best to make it a global or local variable, doing so would save memory, but would probably be fractionaly slower (but not enough to be worth changing).

This code will be faster as we have integrated the letter hashing

CODE

string IntegerAlphabetHash(string score2)
{
string NewScore;
integer scorelength = llStringLength(score2);
integer i = 0;
integer ii;
while(i < scorelength)
{
if(ii = ~llSubStringIndex(HashTable, llGetSubString("ZABCDEFGHIJ01234567890",i,i)))
NewScore += llGetSubString("ZABCDEFGHIJ01234567890", ii, ii);
else //for speed reasons i would probably remove this error checking
NewScore += llGetSubString(score2,i,i);
++i;
}
while(i < maxDigits)
{
NewScore = "Z" + NewScore;
++i;
}
return NewScore;
}
_____________________
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
Blain Candour
Registered User
Join date: 17 Jun 2005
Posts: 83
08-16-2005 23:00
Alright I got all of that except 1 thing. WHy in the world is ++i faster than i++?
_____________________
DISCLAIMER: Blain Candour is a total and eternal n00b and everything he tells you should be taken with a huge pile of salt. Especially when he refers to himself in third person!
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
08-16-2005 23:54
What happens in the bytecode:

CODE

//i++;
push value found at i into the stack
push value found at i into the stack
push integer value 1 into the stack
pop 2 values from the stack add them and push the result back into the stack
peak 1 value from the stack and store it to the memory address i
pop 1 value
pop 1 value

//++i;
push value found at i into the stack
push integer value 1 into the stack
pop 2 values from the stack add them and push the result back into the stack
peak 1 value from the stack and store it to the memory address i
pop 1 value


The difference is 6 bytes. If recollection serves you shave either 2/1000's (or was it 2/10000?) of a second off.
_____________________
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