Author Topic: Sorting Objects From A - Z  (Read 1991 times)

I need to sort some script objects from A - Z and I have now idea how to go about this. Any ideas?
« Last Edit: June 12, 2013, 10:27:19 AM by jes00 »

I have this saved in a file in my Blockland folder, I don't remember where I got it from.
If I remember right it was really bad

Code: [Select]
new SimGroup(leakSet);
rootGroup.add(leakSet);

// Sorts unordered set %uSet, which must be of the class SimSet.
function Quicksort(%uSet)
{
    %less = new SimSet();
    %pivots = new SimSet();
    %greater = new SimSet();
leakSet.add(%less);
leakSet.add(%pivots);
leakSet.add(%greater);

    if(%uSet.getCount() <= 1)
        return %uSet;

    %pivotVal = %uSet.getObject(getRandom(0, %uSet.getCount()-1)).myValue;
    for(%i = 0; %i < %uSet.getCount(); %i ++)
    {
       // A new SimObject must be created in order to store it in a SimSet.
       %valObj = new SimObject(val)
       {
          myValue = %uSet.getObject(%i).myValue;
       };

        if(%pivotVal > %valObj.myValue)
            %less.add(%valObj);
        else if(%pivotVal == %valObj.myValue)
            %pivots.add(%valObj);
        else //if(%pivotVal < %valObj.myValue)
            %greater.add(%valObj);
    }

    return qConcatenate(Quicksort(%less), %pivots, Quicksort(%greater));
}

function qConcatenate(%less, %equal, %greater)
{
    %all = new SimSet();

    // Concatenate the three arrays, adding them to the SimSet one at a time.
    for(%i = 0; %i < %less.getCount(); %i ++)
    {
        %all.add(%less.getObject(%i));
    }
    for(%i = 0; %i < %equal.getCount(); %i ++)
    {
        %all.add(%equal.getObject(%i));
    }
    for(%i = 0; %i < %greater.getCount(); %i ++)
    {
        %all.add(%greater.getObject(%i));
    }

    return %all;
}

function testSort()
{
//Create a SimSet
%unsorted = new SimSet();

//Add the values from the array to the SimSet
for(%i=0;%i<$sorttestamount;%i++)
{
%unsorted.add(%t = new ScriptObject());
%t.myValue = getRandom(0,100);
}

//Sort it
%start = getRealTime();
%sorted = quicksort(%unsorted);
%time = getRealTime() - %start;

//Echo the sorted values
for(%i=0;%i<%sorted.getCount();%i++)
{
echo(%sorted.getObject(%i).myValue);
}
echo("Completed sorting " @ $sorttestamount @ " numbers in " @ %time @ "ms");

}

$sorttestamount = 10000;

sort_list(list) takes a tab-separated list of values as a string and returns it in the same format but ordered based on the return value of do_single_sort(left, right).
Uses no objects or anything like that, just simple string manipulation. This is some pretty old code so I apologize for how unreadable it is.

Code: [Select]
$alpha = "abcdefghijklmnopqrstuvwxyz_";

function sort_list( %m )
{
%count = getFieldCount( %m );

if ( !strLen( %m ) || %count <= 1 )
{
return %m;
}

%middle = mFloor( %count / 2 );

for ( %i = 0 ; %i < %middle ; %i++ )
{
%left = %left @ ( strLen( %left ) ? "\t" : "" ) @ getField( %m, %i );
}

for ( %i = %middle ; %i < %count ; %i++ )
{
%right = %right @ ( strLen( %right ) ? "\t" : "" ) @ getField( %m, %i );
}

%left = merge_sort( %left );
%right = merge_sort( %right );

return merge( %left, %right );
}

function do_single_sort( %left, %right )
{
// I'm pretty sure you can just use strStr instead of this mess.

%lln = strLen( %left );
%rln = strLen( %right );

if ( %lln < %rln )
{
%ln = %lln;
%rt = 1;
}
else
{
%ln = %rln;
%rt = 0;
}

for ( %i = 0 ; %i < %ln ; %i++ )
{
%lfs = getSubStr( %left, %i, 1 );
%rfs = getSubStr( %right, %i, 1 );

%lps = strPos( $alpha, %lfs );
%rps = strPos( $alpha, %rfs );

if ( %lps > %rps )
{
return 1;
}

if ( %rps > %lps )
{
return 0;
}
}

return %rt;
}

function merge( %left, %right )
{
%left = strReplace( %left, " ", "\x01" );
%left = strReplace( %left, "\t", " " );

%right = strReplace( %right, " ", "\x01" );
%right = strReplace( %right, "\t", " " );

while( getWordCount( %left ) > 0 || getWordCount( %right ) > 0 )
{
if ( getWordCount( %left ) > 0 && getWordCount( %right ) > 0 )
{
if ( !do_single_sort( firstWord( %left ), firstWord( %right ) ) )
{
%result = %result @ ( strLen( %result ) ? "\t" : "" ) @ firstWord( %left );
%left = restWords( %left );
}
else
{
%result = %result @ ( strLen( %result ) ? "\t" : "" ) @ firstWord( %right );
%right = restWords( %right );
}
}
else if ( getWordCount( %left ) > 0 )
{
%result = %result @ ( strLen( %result ) ? "\t" : "" ) @ firstWord( %left );
%left = restWords( %left );
}
else if ( getWordCount( %right ) > 0 )
{
%result = %result @ ( strLen( %result ) ? "\t" : "" ) @ firstWord( %right );
%right = restWords( %right );
}
}

%left = strReplace( %left, " ", "\t" );
%left = strReplace( %left, "\x01", " " );

%right = strReplace( %right, " ", "\t" );
%right = strReplace( %right, "\x01", " " );

return %result;
}

Specifically, this implements the merge sort algorithm and is O(log n).
« Last Edit: June 11, 2013, 12:12:44 PM by Port »

Code: [Select]
//in: %word[]
//     %count

%sorter = new GuiTextListCtrl(){};
for(%i = 0; %i < %count; %i++)
%sorter.addRow(%i, %word[%i]);
%sorter.sort(0,1);
for(%i = 0; %i < %sorter.rowCount(); %i++)
%sorted[%i] = %sorter.getRowText(%i);
%sorter.delete();

//out: %sorted[]
Why are you guys doing it so complicated
« Last Edit: June 11, 2013, 02:31:56 PM by Zeblote »

Code: [Select]
//in: %word[]
//     %count

%sorter = new GuiTextListCtrl(){};
for(%i = 0; %i < %count; %i++)
%sorter.addRow(%i, %word[%i]);
%sorter.sort(0,1);
for(%i = 0; %i < %sorter.rowCount(); %i++)
%sorted[%i] = %sorter.getRowText(%i);

//out: %sorted[]
Why are you guys doing it so complicated

Because this requires objects and has extremely low flexibility.

Because this requires objects and has extremely low flexibility.
How does it have low flexibility and what is wrong with creating one object?

How does it have low flexibility

What if I wanted to sort by something other than the default sequence that GuiTextListCtrl::sort uses?

and what is wrong with creating one object?

The fact that you're creating an object using the conobject class GuiTextListCtrl, populating it with data, calling one method and deleting it to do something as simple as sorting strings should be an immediate pointer to that you're doing something wrong. Think about it for a second.

What if I wanted to sort by something other than the default sequence that GuiTextListCtrl::sort uses?
He said sort from A to Z
The fact that you're creating an object using the conobject class GuiTextListCtrl, populating it with data, calling one method and deleting it to do something as simple as sorting strings should be an immediate pointer to that you're doing something wrong. Think about it for a second.
It's not like it's going to run slower, cause lag or other potential issues

There are lots and lots of ways to sort things. (more info)

Here's a pretty basic bubble-sort method. It works fine up to a point. (I should probably make something more efficient..)

Code: [Select]
function MinigameSO::getMemberListSortedScore(%this)
{
%count = %this.numMembers;
for(%i = 0; %i < %count; %i ++)
%list = setField(%list,getFieldCount(%list),%this.member[%i]);

while(!%done)
{
%done = 1;
for(%i = 0; %i < %count; %i ++)
{
%e = %i + 1;
if(%e >= %count)
continue;
%f1 = getField(%list,%i);
%f2 = getField(%list,%e);
if(%f1.score < %f2.score)
{
%list = Slayer_Support::swapItemsInList(%list,%i,%e);
%done = 0;
}
}
%count --;
}
return %list;
}

The fact that you're creating an object using the conobject class GuiTextListCtrl, populating it with data, calling one method and deleting it to do something as simple as sorting strings should be an immediate pointer to that you're doing something wrong. Think about it for a second.

Or think about it for a little longer. The performance you get from doing sorting in a scripting engine is going to be stuff no matter what you say. Outsourcing the actual sorting to the engine is always going to give you better performance. I do this plenty in RTB and I know it's used in Blockland code. It is the best option.

jes00 - go with the code Zeblote has supplied. You can make it do essentially whatever you need it to.
« Last Edit: June 11, 2013, 01:50:57 PM by Ephialtes »

Or think about it for a little longer. The performance you get from doing sorting in a scripting engine is going to be stuff no matter what you say. Outsourcing the actual sorting to the engine is always going to give you better performance. I do this plenty in RTB and I know it's used in Blockland code. It is the best option.

jes00 - go with the code Zeblote has supplied. You can make it do essentially whatever you need it to.


Does that work on a server as well?

Can't figure out why it's not working.

Code: [Select]
for(%i = 0; %i < ArcadeSystem.getCount(); %i++)
{
%word[%count++] = ArcadeSystem.getObject(%i).name;
}

%sorter = new GuiTextListCtrl() {};

for(%i = 0; %i < %count; %i++)
{
%sorter.addRow(%i, %word[%i]);
}

%sorter.sort(0, 1);

for(%i = 0; %i < %sorter.rowCount(); %i++)
{
%sorted[%i] = %sorter.getRowText(%i);
}

for(%i = 0; %i < %sorter.rowCount(); %i++)
{
for(%ii = 0; %ii < ArcadeSystem.getCount(); %ii++)
{
if(ArcadeSystem.getObject(%ii).name $= %sorted[%i])
{
ArcadeSystem.bringToFront(ArcadeSystem.getObject(%ii));

echo("\c2Brought" SPC ArcadeSystem.getObject(%ii).name SPC "To front.");

break;
}
}
}

%sorter.delete();



Does that work on a server as well?
I just did a simple test:

Looks like it does.
« Last Edit: June 26, 2013, 03:37:13 PM by Zeblote »