You need to sign in to do that
Don't have an account?
CRMfusion - GW
Sorting arrays
Any ideas on how to sort an array?
My plan is to build a bubble sort method but I'm not sure if it will eat up too many "script statements" on a large array.
GlennW
My plan is to build a bubble sort method but I'm not sure if it will eat up too many "script statements" on a large array.
GlennW
This should be a method of the array objects as the number of script statements needed for larger arrays could blow past the script before DML govenor.
glenn.wilson@crmfusion.com
FYI. Here is the code
/*************************************************************/
/* */
/* Method to sort a string array using a bubble sort */
/* */
/* */
/*************************************************************/
public void BubbleSort(String[] inArray) {
Boolean swapped = false;
do {
swapped = false;
for (Integer i = 0; i < (inArray.size() - 1); i++){
if (inArray[i] > inArray[i + 1]) {
swap(inArray, i, i+1);
swapped = true;
} // if
} // for
} while (swapped == true);
} // method
/*************************************************************/
/* */
/* Method to swap 2 string array elements */
/* */
/* */
/*************************************************************/
private void swap(String[] inArray, Integer idx, Integer jdx) {
String tempStr;
tempStr = inArray[idx];
inArray[idx] = inArray[jdx];
inArray[jdx] = tempStr;
}
Message Edited by CRMfusion - GW on 03-07-2007 08:15 AM
Code:
When you run using this example data, you end up with the following runtime results:
Results:
This is a lot of code coverage for a 21-indice array. I sought to bring that number down so it can be used with larger arrays:
Code:
This code checks each indice and locates the lowest value, then swaps it out over each pass, instead of moving it one indice down. However, it sometimes performs unnecessary swaps. The overall results of my sample were still fairly impressive.
Results:
As you can see, from the original 747 lines, it's now down to 438 lines. That's 58% of the original footprint, which is impressive. However, it's still very inefficient. Imagine running a list of 1000 items-- it would run to be extremely large, and might not complete successfully. So, I optimized a bit more and came up with the following code.
Code:
I looked at it for a while and made sure it worked correctly, since it looks almost too good to be true. Then, I ran the code and tested it, and came up with some amazing results. After getting these results, I even had to doublecheck to see if the sort was finishing correctly. Here's why...
Results:
Amazing! I just went from 438 lines to only 167 lines, just by doubling up one loop... So, for the record, that translates to 22% of the original posted code, and 38% of my first attempt at a sorting algorithm. I hope someone finds this algorithm interesting and even useful. This algorithm does have dependencies on the order of the values (most algorithms do); even in a worst case scenario, it still uses less cycles than a brute-force method such as bubble sorting.
~ sfdcfox ~
The greatest challenge we'll have in the development of APEC Code apps is managing the govenors and figuring out ways to cut the script calls to a minimum. This will help cut that down significantly.
Cheers;
GlennW
With the algorithm above, here are the results I get:
Rather than dig through this code to find the error I decided to focus my time an creating a new, potentially better, sorting algorithm. After doing some research it seems like the quicksort algorithm is one of the better algorithms that isn't overly complicated. I have taken this algorithm and converted it to Apex. I must give credit where credit is due as I didn't come up with this all on my own but used this site ( http://www.cs.ubc.ca/~harrison/Java/sorting-demo.html ) and don't worry the author has given permission to use this code in commercial and non-commercial applications so feel free to use it.
You can test the two algorithms by creating the class below and then entering these lines in the system log.
sortTest testing = new sortTESt('quick');
sortTest testing = new sortTESt('dsort');
The quick sort method seems pretty efficient but I plan to do more testing and will report back.
Message Edited by TehNrd on 09-22-2008 09:40 AM
I created a random List of 1000 Integers and then ran this quick sort about 10 times. The average number of script statements was near 25,000. This is the first algorithm that has actually allowed me to sort a full List of 1000 elements so I am happy.
One thing about this quicksort algorithm is that it sorts ascending. I will try to rework the code so you can enter an extra parameter to define ascending or descending sort order. If successful I'll report back and post the code.
Code for creating a random Integer list:
Message Edited by TehNrd on 09-22-2008 10:53 AM
I totally agree, use sort() on primitive data sets. The example I have supplied is providing a sort algorithm for a primitive data type but this could be easy converted to sort a list of sObjects. Lets say you had an List of Opportunities. Anywhere you see comparisons or the code referencing an index you would need to access the opp Amount:
while (a[lo] <= pivot && lo < hi){
you would change to:
while (a[lo].Amount <= pivot && lo < hi){
where 'a' is a list of opps.
-Jason
Message Edited by TehNrd on 09-22-2008 10:08 AM
I basically put the values that want sorting into a seperate list, put the unsorted values into a map with the Key as the values I want sorting, and a list of Opportunities as the value. I then sort my list of values to sort, then loop through the sorted values and get the Opportunities from the Map.
I tried this on 6 opportunities at first to see if they were successfully sorted, and it seemed to turn out well. Next, I created 1000 opportunities and used those with the random number generator provided earlier in this thread. This is what I got:
Testing resources:
Resource usage for namespace: (default)
Number of SOQL queries: 0 out of 100
Number of query rows: 0 out of 10000
Number of SOSL queries: 0 out of 20
Number of DML statements: 0 out of 100
Number of DML rows: 0 out of 10000
Number of script statements: 7006 out of 200000
Maximum heap size: 52418 out of 1000000
Number of callouts: 0 out of 10
Number of Email Invocations: 0 out of 10
Number of fields describes: 0 out of 10
Number of record type describes: 0 out of 10
Number of child relationships describes: 0 out of 10
Number of picklist describes: 0 out of 10
Number of future calls: 0 out of 10
Hope I did the System.Test.StartTest correctly to provide accurate results. If not, here is what I got without using StartTest and StopTest:
Cumulative resource usage:
Resource usage for namespace: (default)
Number of SOQL queries: 0 out of 100
Number of query rows: 0 out of 500
Number of SOSL queries: 0 out of 20
Number of DML statements: 0 out of 100
Number of DML rows: 0 out of 500
Number of script statements: 11013 out of 200000
Maximum heap size: 52594 out of 500000
Number of callouts: 0 out of 10
Number of Email Invocations: 0 out of 10
Number of fields describes: 0 out of 10
Number of record type describes: 0 out of 10
Number of child relationships describes: 0 out of 10
Number of picklist describes: 0 out of 10
Number of future calls: 0 out of 10
Anyone else want to try this out?
edit: Only one of the opps with the duplicate amount will make it to the returned list. So your returned list will actually be smaller that the list you sent for sorting.
Message Edited by TehNrd on 09-23-2008 12:59 PM
Awhile ago I actually tried something similar to what XactiumBen was doing where I would add something on the end of the amount to make it unique and then try to sort. The problem was this turned the list of Numbers into strings and the sort then doesn't work correctly.
-Jason
Message Edited by TehNrd on 09-23-2008 01:02 PM
Link below should read: "Sorting collections in Apex and "Too many script statements"" instead of "Link:"
Sorting collections in Apex and "Too many script statements"
XactiumBen wrote:
In answer to your previous question about duplicates, I use a List of Opportunities in my Map so it can store lots of Opportunities per unique key:
Whoops I totally overlooked that. Looks like Andrew's method is very similar but he uses the addAll() method.
I've done some testing on Lists of 1000 and with the custom quick sort method and it averages around 24,000 statements. With the cool standard sort it uses around 2,600. Very nice.
My next challenge, an efficient algorithm to add values to an already sorted list. I've describe how I would try that here but I have yet to actually code it. http://community.salesforce.com/sforce/board/message?board.id=Visualforce&message.id=5394#M5394 but depending on Andrew's next blog post I may not have to do this.
Message Edited by TehNrd on 09-25-2008 09:21 AM